如何在Android中实现json的离线缓存?

时间:2014-10-01 07:03:32

标签: android json caching

我正在研究像techcrunch这样的文章应用程序我正在从json解析数据。 我正在从json解析标题,作者和图像。 文章显示在列表视图中。 我想做离线缓存意味着当没有互联网用户可以阅读文章时。

这是我的代码 -

public class OneFragment extends Fragment {

public OneFragment(){}
private static final String TAG = OneFragment.class.getSimpleName();

// Movies json url
private static String URL = "http://url";
private ProgressDialog pDialog;
private List<Movie> movieList = new ArrayList<Movie>();
private ListView listView;
private CustomListAdapter adapter;
int current_page = 0;
int mPreLast;
SwipeRefreshLayout swipeView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    final View rootView = inflater.inflate(R.layout.swip, container, false);
    swipeView = (SwipeRefreshLayout) rootView.findViewById(R.id.swipe);
    swipeView.setColorScheme(android.R.color.holo_blue_dark, android.R.color.holo_blue_light, android.R.color.holo_green_light, android.R.color.holo_green_dark);
    pDialog = new ProgressDialog(getActivity());
    pDialog.setMessage("Loading...");
    pDialog.show();
    pDialog.setCancelable(false);

    swipeView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {

        @Override
        public void onRefresh() {
            // TODO Auto-generated method stub
            swipeView.setRefreshing(true);
            Log.d("Swipe", "Refreshing Number");
            ( new Handler()).postDelayed(new Runnable() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    swipeView.setRefreshing(false);
                    onStart();
                }
            }, 3000);
        }
    });

    listView = (ListView) rootView.findViewById(R.id.list49);
    listView.setOnScrollListener(new AbsListView.OnScrollListener()
    {
        @Override
        public void onScrollStateChanged(AbsListView absListView, int i)
        {

        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
        {
            int lastItem = firstVisibleItem + visibleItemCount;
               if(lastItem == totalItemCount){
                   if (mPreLast != lastItem)
                   {
                        mPreLast = lastItem;                           
                        pDialog = new ProgressDialog(getActivity());
                        pDialog.setMessage("Loading more articles...");
                        pDialog.show();
                        //pDialog.setCancelable(false);
                        onStart(); 
                   }
            }
        }
    });

    listView.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(AdapterView<?>  adapterView, View view, int Position,
                long offset)  { 
            // TODO Auto-generated method stub
            Movie item = (Movie) adapter.getItem(Position);             
            Intent intent = new Intent(rootView.getContext(), SingleArticle.class);
            single.title = item.getTitle();
            single.author = item.getAuthor();

            startActivity(intent);


            }        
        });
    //pDialog = new ProgressDialog(this);
    // Showing progress dialog before making http request

    return rootView;
}

@Override
public void onStart(){
    super.onStart();
    // calling adapter changes here, just
    // to avoid getactivity()null
    // increment current page
     current_page += 1;
    // Next page request
    URL = "http://url" + current_page;
    //adapter = new CustomListAdapter(this, movieList);
    int currentPosition = listView.getFirstVisiblePosition();
    adapter = new CustomListAdapter(getActivity(), movieList);
    listView.setAdapter(adapter);
    listView.setSelectionFromTop(currentPosition + 1, 0);
    // changing action bar color
    //getActivity().getActionBar().setBackground(
            //new ColorDrawable(Color.parseColor("#1b1b1b")));

    // Creating volley request obj
    JsonArrayRequest movieReq = new JsonArrayRequest(URL,
            new Response.Listener<JSONArray>() {

                @Override
                public void onResponse(JSONArray response) {

                    Log.d(TAG, response.toString());
                    hidePDialog();

                    // Parsing json
                    for (int i = 0; i < response.length(); i++) {
                        try {

                            JSONObject obj = response.getJSONObject(i);
                            Movie movie = new Movie();
                            movie.setTitle(obj.getString("title"));
                            movie.setAuthor(obj.getString("author"));
                            // adding movie to movies array
                            movieList.add(movie);




                            adapter.notifyDataSetChanged();

                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }                       
                }
            },new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    VolleyLog.d(TAG, "Error: " + error.getMessage());
                    new AlertDialog.Builder(getActivity())
                    .setTitle("No Connectivity ")
                    .setMessage("Please check your internet connectivity!")
                    .setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) { 
                            // continue with delete
                        }
                     })
                    //.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
                        //public void onClick(DialogInterface dialog, int which) { 
                            // do nothing
                        //}
                     //})
                    .setIcon(android.R.drawable.ic_dialog_alert)
                     .show();
                    hidePDialog();

                }
            });
    AppController.getInstance().addToRequestQueue(movieReq);    
    //listView.setAdapter(adapter);

}

private View getActionBar() {
    // TODO Auto-generated method stub
    return null;
}

@Override
public void onDestroy() {
super.onDestroy();
hidePDialog();
}

private void hidePDialog() {
if (pDialog != null) {
    pDialog.dismiss();
    pDialog = null;
}
}
}

3 个答案:

答案 0 :(得分:3)

这可能不是最好的方法,但它对我有用。

您可能会发现这有用:http://www.vogella.com/tutorials/JavaSerialization/article.html

我必须在某个项目中做同样的事情。这就是我所做的:

public final class cacheThis {
private cacheThis() {}

public static void writeObject(Context context, String fileName, Object object) throws IOException {
      FileOutputStream fos = context.openFileOutput(fileName, Context.MODE_PRIVATE);
      ObjectOutputStream oos = new ObjectOutputStream(fos);
      oos.writeObject(object);
      oos.flush();
      oos.close();

      fos.close();
   }

   public static Object readObject(Context context, String fileName) throws IOException,
         ClassNotFoundException {
      FileInputStream fis = context.openFileInput(fileName);
      ObjectInputStream ois = new ObjectInputStream(fis);
      Object object = ois.readObject();
      fis.close();
      return object;
   }
}

要写入文件:

cacheThis.writeObject(YourActivity.this, fileName, movieList);

从文件中读取:

movieList.addAll((List<Movie>) cacheThis.readObject(
                VideoActivity.this, fileName));

您必须拥有电影课程implements Serializable

答案 1 :(得分:1)

您必须将json保存为脱机状态。它可以是Db或文件系统。我更愿意选择Db部分。

方法是,每次从服务器获取数据时,首先从db中获取数据,然后从db中获取数据,然后将其显示在UI中。

在Db中插入可能很慢,但您可以使用beginTransaction和其他方法来快速点亮。

现在如何在Db中保存数据。你有两种方式

  • 您可以先解析json,然后为name,url和其他字段创建表结构,然后运行查询

  • 或者将整个json存储在Db中而不进行解析。通过使用GSON或其他json解析器,这个approch将非常有用。

答案 2 :(得分:1)

我看到你正在使用Volley。 Volley内置了HTTP Cache机制。

  • 所以最简单的方法是在后端支持HTTP缓存头。它非常简单,对客户端来说是透明的。 Volley做了很多努力。您可以找到信息here

  • 如果您无法访问所使用的URL,则必须使用内部数据库来支持您的应用程序。 ContentProvider API是执行此操作的最佳方式。以下库是构建数据库并写入数据库的绝佳库。 https://github.com/TimotheeJeannin/ProviGen

基本上,您需要将从互联网上提取的每个项目写入数据库,ListView应使用您刚刚创建的ContentProvider显示数据库中的项目。当用户打开应用程序时,显示数据库中的数据,然后立即尝试从后端提取新数据。