如何缓存解析的JSON用于离线使用 [英] How to Cache Parsed JSON for Offline usage

查看:184
本文介绍了如何缓存解析的JSON用于离线使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经JSON解析成功,但现在我想缓存它离线使用,即使是网络不可用,如果有任何新的项目来了,我想缓存这一点。

和什么是缓存数据的最佳选择? 共享preferences SQLite数据库

下面是我的code,而我使用到JSON解析:

 公共类MainActivity延伸活动{

    ArrayList的<演员> actorsList;
    ActorAdapter适配器;

    @覆盖
    保护无效的onCreate(包savedInstanceState){
        super.onCreate(savedInstanceState);
        的setContentView(R.layout.activity_main);
        actorsList =新的ArrayList<演员>();
        新JSONAsyncTask()执行(http://microblogging.wingnity.com/JSONParsingTutorial/jsonActors);

        ListView控件列表视图=(ListView控件)findViewById(R.id.list);
        适配器=新ActorAdapter(getApplicationContext(),R.layout.row,actorsList);

        listview.setAdapter(适配器);

        listview.setOnItemClickListener(新OnItemClickListener(){

            @覆盖
            公共无效onItemClick(适配器视图<>为arg0,查看ARG1,INT位置,
                    长ID){
                // TODO自动生成方法存根
                Toast.makeText(getApplicationContext(),actorsList.get(位置).getName(),Toast.LENGTH_LONG).show();
            }
        });
    }


    类JSONAsyncTask扩展的AsyncTask<字符串,太虚,布尔> {

        ProgressDialog对话框;

        @覆盖
        在preExecute保护无效(){
            super.on preExecute();
            对话框=新ProgressDialog(MainActivity.this);
            dialog.setMessage(载入中,请稍候);
            dialog.setTitle(连接服务器);
            dialog.show();
            dialog.setCancelable(假);
        }

        @覆盖
        保护布尔doInBackground(字符串...网址){
            尝试 {

                // ------------------>>
                HTTPGET httppost =新HTTPGET(网址[0]);
                HttpClient的HttpClient的=新DefaultHttpClient();
                HTT presponse响应= httpclient.execute(httppost);

                //状态行STAT = response.getStatusLine();
                。INT状态= response.getStatusLine()的getStatus code();

                如果(状态== 200){
                    HttpEntity实体= response.getEntity();
                    字符串数据= EntityUtils.toString(实体);


                    JSONObject的jsono =新的JSONObject(数据);
                    JSONArray jarray = jsono.getJSONArray(演员);

                    的for(int i = 0; I< jarray.length();我++){
                        的JSONObject对象= jarray.getJSONObject(我);

                        演员演员=新演员();

                        actor.setName(object.getString(名字));
                        actor.setDescription(object.getString(说明));

                        actorsList.add(演员);
                    }
                    返回true;
                }

                // ------------------>>

            }赶上(ParseException的E1){
                e1.printStackTrace();
            }赶上(IOException异常E){
                e.printStackTrace();
            }赶上(JSONException E){
                e.printStackTrace();
            }
            返回false;
        }

        保护无效onPostExecute(布尔结果){
            dialog.cancel();
            adapter.notifyDataSetChanged();
            如果(结果==假)
                Toast.makeText(getApplicationContext(),无法获取来自服务器的数据,Toast.LENGTH_LONG).show();

        }
    }

}
 

解决方案

为什么不直接使用它像这样保存到你的应用程序的缓存文件夹:

 字符串路径= Environment.getExternalStorageDirectory()+文件分割符+缓存+文件分割符;
文件DIR =新的文件(路径);
如果(!dir.exists()){
    dir.mkdirs();
}
路径+ =数据;
文件数据=新的文件(路径);
如果(!data.createNewFile()){
    data.delete();
    data.createNewFile();
}
ObjectOutputStream的ObjectOutputStream的=新的ObjectOutputStream(新的FileOutputStream(数据));
objectOutputStream.writeObject(actorsList);
objectOutputStream.close();
 

和之后,你可以使用在任何时候读它:

 名单,其中;>名单= NULL;
文件数据=新的文件(路径);
尝试 {
    如果(data.exists()){
        ObjectInputStream的ObjectInputStream的=新的ObjectInputStream(新的FileInputStream(数据));
        名单=(名单<对象>)objectInputStream.readObject();
        objectInputStream.close();
    }
}赶上(IOException异常E){
    e.printStackTrace();
}赶上(ClassNotFoundException异常E){
    e.printStackTrace();
}
 

更新:好吧,请叫ObjectToFileUtil类,粘贴此code到创建的类<​​/ P>

 包装&LT; yourpackagehere取代;

进口android.os.Environment;

进口java.io. *;

公共类ObjectToFileUtil {

    公共静态字符串objectToFile(Object对象)抛出IOException异常{
        字符串路径= Environment.getExternalStorageDirectory()+文件分割符+缓存+文件分割符;
        文件DIR =新的文件(路径);
        如果(!dir.exists()){
            dir.mkdirs();
        }
        路径+ =数据;
        文件数据=新的文件(路径);
        如果(!data.createNewFile()){
            data.delete();
            data.createNewFile();
        }
        ObjectOutputStream的ObjectOutputStream的=新的ObjectOutputStream(新的FileOutputStream(数据));
        objectOutputStream.writeObject(对象);
        objectOutputStream.close();
        返回路径;
    }

    公共静态对象objectFromFile(字符串路径)抛出IOException异常,ClassNotFoundException异常{
        Object对象= NULL;
        文件数据=新的文件(路径);
        如果(data.exists()){
            ObjectInputStream的ObjectInputStream的=新的ObjectInputStream(新的FileInputStream(数据));
            对象= objectInputStream.readObject();
            objectInputStream.close();
        }
        返回对象;
    }
}
 

变化与LT; yourpackagehere>你的包名,不要忘了加上 WRITE_EXTERNAL_STORAG​​E 许可 AndroidManifest.xml中。在您的MainActivity添加字段

 私人字符串数据路径;
 

和更换JSONAsyncTask类的onPostExecute方法

 保护无效onPostExecute(布尔结果){
    dialog.cancel();
    adapter.notifyDataSetChanged();
    如果(结果){
        尝试 {
            数据路径= objectToFile(ArrayList中);
        }赶上(IOException异常E){
            e.printStackTrace();
        }
    } 其他 {
        Toast.makeText(getApplicationContext(),无法获取来自服务器的数据,Toast.LENGTH_LONG).show();
    }
}
 

现在您可以访问文件随时得到actorsList使用,当你想,

 尝试{
    actorsList =(ArrayList的&LT;演员&GT;)objectFromFile(数据路径);
}赶上(IOException异常E){
    e.printStackTrace();
}赶上(ClassNotFoundException异常E){
    e.printStackTrace();
}
 

如果你想关闭应用程序,您必须保存数据路径字符串(和负载在应用程序启动),例如后保存文件的路径,使用<一个href="http://stackoverflow.com/questions/3624280/how-to-use-shared$p$pferences-in-android-to-store-fetch-and-edit-values">Shared$p$pferences.

I have parsed JSON successfully but now i want to Cache it for offline usage, even internet is not available, and if any new entry comes i want to cache that as well.

And what would be the best option to cache data ? SharedPreferences or SQLite database

Here is my code, which i am using to Parse JSON:

public class MainActivity extends Activity {

    ArrayList<Actors> actorsList;   
    ActorAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        actorsList = new ArrayList<Actors>();
        new JSONAsyncTask().execute("http://microblogging.wingnity.com/JSONParsingTutorial/jsonActors");

        ListView listview = (ListView)findViewById(R.id.list);
        adapter = new ActorAdapter(getApplicationContext(), R.layout.row, actorsList);

        listview.setAdapter(adapter);

        listview.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int position,
                    long id) {
                // TODO Auto-generated method stub
                Toast.makeText(getApplicationContext(), actorsList.get(position).getName(), Toast.LENGTH_LONG).show();              
            }
        });
    }


    class JSONAsyncTask extends AsyncTask<String, Void, Boolean> {

        ProgressDialog dialog;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            dialog = new ProgressDialog(MainActivity.this);
            dialog.setMessage("Loading, please wait");
            dialog.setTitle("Connecting server");
            dialog.show();
            dialog.setCancelable(false);
        }

        @Override
        protected Boolean doInBackground(String... urls) {
            try {

                //------------------>>
                HttpGet httppost = new HttpGet(urls[0]);
                HttpClient httpclient = new DefaultHttpClient();
                HttpResponse response = httpclient.execute(httppost);

                // StatusLine stat = response.getStatusLine();
                int status = response.getStatusLine().getStatusCode();

                if (status == 200) {
                    HttpEntity entity = response.getEntity();
                    String data = EntityUtils.toString(entity);


                    JSONObject jsono = new JSONObject(data);
                    JSONArray jarray = jsono.getJSONArray("actors");

                    for (int i = 0; i < jarray.length(); i++) {
                        JSONObject object = jarray.getJSONObject(i);

                        Actors actor = new Actors();

                        actor.setName(object.getString("name"));
                        actor.setDescription(object.getString("description"));

                        actorsList.add(actor);
                    }
                    return true;
                }

                //------------------>>

            } catch (ParseException e1) {
                e1.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (JSONException e) {
                e.printStackTrace();
            }
            return false;
        }

        protected void onPostExecute(Boolean result) {
            dialog.cancel();
            adapter.notifyDataSetChanged();
            if(result == false)
                Toast.makeText(getApplicationContext(), "Unable to fetch data from server", Toast.LENGTH_LONG).show();

        }
    }

}

解决方案

Why not just save it to cache folder of your app using something like this:

String path = Environment.getExternalStorageDirectory() + File.separator + "cache" + File.separator;
File dir = new File(path);
if (!dir.exists()) {
    dir.mkdirs();
}
path += "data";
File data = new File(path);
if (!data.createNewFile()) {
    data.delete();
    data.createNewFile();
}
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(data));
objectOutputStream.writeObject(actorsList);
objectOutputStream.close();

And after, you can read it in any time using:

List<?> list = null;
File data = new File(path);
try {
    if(data.exists()) {
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(data));
        list = (List<Object>) objectInputStream.readObject();
        objectInputStream.close();
    }
} catch (IOException e) {
    e.printStackTrace();
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

UPDATE: Okay, make class named ObjectToFileUtil, paste this code to created class

package <yourpackagehere>;

import android.os.Environment;

import java.io.*;

public class ObjectToFileUtil {

    public static String objectToFile(Object object) throws IOException {
        String path = Environment.getExternalStorageDirectory() + File.separator + "cache" + File.separator;
        File dir = new File(path);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        path += "data";
        File data = new File(path);
        if (!data.createNewFile()) {
            data.delete();
            data.createNewFile();
        }
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(data));
        objectOutputStream.writeObject(object);
        objectOutputStream.close();
        return path;
    }

    public static Object objectFromFile(String path) throws IOException, ClassNotFoundException {
        Object object = null;
        File data = new File(path);
        if(data.exists()) {
            ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(data));
            object = objectInputStream.readObject();
            objectInputStream.close();
        }
        return object;
    }
}

Change < yourpackagehere > to your package name and don't forget to add WRITE_EXTERNAL_STORAGE permission to AndroidManifest.xml. In your MainActivity add field

private String dataPath;

and replace your onPostExecute method of JSONAsyncTask class to

protected void onPostExecute(Boolean result) {
    dialog.cancel();
    adapter.notifyDataSetChanged();
    if(result) {
        try {
            dataPath = objectToFile(arrayList);
        } catch (IOException e) {
            e.printStackTrace();
        }
    } else {
        Toast.makeText(getApplicationContext(), "Unable to fetch data from server", Toast.LENGTH_LONG).show();
    }
}

Now you can access get actorsList from File anytime when you want, by using

try {
    actorsList = (ArrayList<Actors>)objectFromFile(dataPath);
} catch (IOException e) {
    e.printStackTrace();
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

If you want to save path of file after closing application you must save dataPath string (and load on application start), for example, using SharedPreferences.

这篇关于如何缓存解析的JSON用于离线使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆