如何缓存Json数据以便脱机使用?

时间:2014-01-30 15:22:56

标签: java android json offline

我已经在listview中解析了JSON数据,现在我想让它脱机使用。 有没有办法在手机上保存JSON数据,以便在手机离线时可以看到数据?

有人知道一个例子吗?

编辑现在可以使用:

 public class MainActivity extends ListActivity {


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        new TheTask().execute();
    }

    class TheTask extends AsyncTask<Void, Void, JSONArray> {
        InputStream is = null;
        String result = "";
        JSONArray jArray = null;

        ProgressDialog pd;

        @Override
        protected void onPostExecute(JSONArray result) {
            super.onPostExecute(result);
            pd.dismiss();
            ArrayList<String> list= new ArrayList<String>();
            try {
                for(int i=0;i<result.length();i++) {

                    JSONObject jb = result.getJSONObject(i) ;
                    String name = jb.getString("name")+" "+jb.getString("Art");
                    list.add(name);
                }
            } catch(Exception e) {
                e.printStackTrace();
            }
            setListAdapter(new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, list));
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pd = ProgressDialog.show(MainActivity.this, "State",
                    "Loading...", true);
        }

        @Override
        protected JSONArray doInBackground(Void... arg0) {
            ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

                try {
                    HttpClient httpclient = new DefaultHttpClient();
                    HttpPost httppost = new HttpPost("***");
                    HttpResponse response = httpclient.execute(httppost);
                    HttpEntity entity = response.getEntity();
                    is = entity.getContent();
                } catch (Exception e) {
                    Log.e("log_tag", "Error in http connection " + e.toString());
                }

                // Convert response to string
                try {
                    BufferedReader reader = new BufferedReader(new InputStreamReader(
                            is, "iso-8859-1"), 8);
                    StringBuilder sb = new StringBuilder();
                    String line = null;
                    while ((line = reader.readLine()) != null) {
                        sb.append(line + "\n");
                    }
                    is.close();
                    result = sb.toString();
                    writeToFile(result);
                } catch (Exception e) {
                    Log.e("log_tag", "Error converting result " + e.toString());
                }

                try {
                    jArray = new JSONArray(result);
                } catch (JSONException e) {
                    Log.e("log_tag", "Error parsing data " + e.toString());
                }

                try {
                    jArray = new JSONArray(readFromFile());
                } catch (JSONException e) {
                    Log.e("log_tag", "Error parsing data " + e.toString());
                }

            return jArray;
        }
    }

    private void writeToFile(String data) {
        try {
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(openFileOutput("config.txt", Context.MODE_PRIVATE));
            outputStreamWriter.write(data);
            outputStreamWriter.close();
        }
        catch (IOException e) {
            Log.e("Exception", "File write failed: " + e.toString());
        }
    }

    private String readFromFile() {

        String ret = "";

        try {
            InputStream inputStream = openFileInput("config.txt");

            if ( inputStream != null ) {
                InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
                BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
                String receiveString = "";
                StringBuilder stringBuilder = new StringBuilder();

                while ( (receiveString = bufferedReader.readLine()) != null ) {
                    stringBuilder.append(receiveString);
                }

                inputStream.close();
                ret = stringBuilder.toString();
            }
        } catch (FileNotFoundException e) {
            Log.e("login activity", "File not found: " + e.toString());
        } catch (IOException e) {
            Log.e("login activity", "Can not read file: " + e.toString());
        }

        return ret;
    }
}

7 个答案:

答案 0 :(得分:15)

你有两种方法。要么创建数据库并将所有数据保存在那里,并在需要时将其检索回来。或者,如果您拥有的数据不是那么多并且您不想处理数据库,那么您将json字符串写入存储卡中的文本文件,并在以后离线时读取它。

对于第二种情况,每次上网时,您都可以从Web服务中检索相同的json,然后将其写入旧的json。这样,您可以确保将最新的json保存到设备中。

答案 1 :(得分:3)

此类将帮助您使用密钥缓存文件中的字符串,以便稍后检索。字符串可以是json字符串,key可以是您请求的url,如果使用post方法,也可以是url的标识符。

public class CacheHelper {

static int cacheLifeHour = 7 * 24;

public static String getCacheDirectory(Context context){

    return context.getCacheDir().getPath();
}

public static void save(Context context, String key, String value) {

    try {

        key = URLEncoder.encode(key, "UTF-8");

        File cache = new File(getCacheDirectory(context) + "/" + key + ".srl");

        ObjectOutput out = new ObjectOutputStream(new FileOutputStream(cache));
        out.writeUTF(value);
        out.close();
    } catch (Exception e) {

        e.printStackTrace();
    }
}

public static void save(Context context, String key, String value, String identifier) {

   save(context, key + identifier, value);
}

public static String retrieve(Context context, String key, String identifier) {

   return retrieve(context, key + identifier);
}


public static String retrieve(Context context, String key) {

    try {

        key = URLEncoder.encode(key, "UTF-8");

        File cache = new File(getCacheDirectory(context) + "/" + key + ".srl");

        if (cache.exists()) {

            Date lastModDate = new Date(cache.lastModified());
            Date now = new Date();

            long diffInMillisec = now.getTime() - lastModDate.getTime();
            long diffInSec = TimeUnit.MILLISECONDS.toSeconds(diffInMillisec);

            diffInSec /= 60;
            diffInSec /= 60;
            long hours = diffInSec % 24;

            if (hours > cacheLifeHour) {
                cache.delete();
                return "";
            }

            ObjectInputStream in = new ObjectInputStream(new FileInputStream(cache));
            String value = in.readUTF();
            in.close();

            return value;
        }

    } catch (Exception e) {

        e.printStackTrace();
    }

    return "";
}
}

如何使用它:

String string = "cache me!";
String key = "cache1";
CacheHelper.save(context, key, string);
String getCache = CacheHelper.retrieve(context, key); // will return 'cache me!'

答案 2 :(得分:0)

下载数据后,您可以使用您喜欢的数据库或系统将数据保存在移动设备上。

您可以在此处查看不同的选项:data-storage

答案 3 :(得分:0)

您可以使用这两种方法将JSON个文件存储为SharedPreferences中的字符串并将其检索回来:

public String getStringProperty(String key) {
    sharedPreferences = context.getSharedPreferences("preferences", Activity.MODE_PRIVATE);
    String res = null;
    if (sharedPreferences != null) {
        res = sharedPreferences.getString(key, null);
    }
    return res;
}

public void setStringProperty(String key, String value) {
    sharedPreferences = context.getSharedPreferences("preferences", Activity.MODE_PRIVATE);
    if (sharedPreferences != null) {
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putString(key, value);
        editor.commit();
        CupsLog.i(TAG, "Set " + key + " property = " + value);
    }
}

只需使用setStringProperty("json", "yourJsonString")保存并getStringProperty("json")进行检索。

答案 4 :(得分:0)

使用SharedPreferences应该准备sqlite(除非你有一个数据库结构)。对于缓存和存储从互联网上提取的数据,我建议使用robospice:https://github.com/octo-online/robospice。它是一个非常完善的库,易于使用,应该在您从Internet下载数据或长时间运行任务时使用。

答案 5 :(得分:0)

  

如何将Json数据缓存到离线状态?

您可以使用gson更轻松地解析JSON数据。 在build.gradle文件中添加此依赖项。

compile 'com.google.code.gson:gson:2.8.0'

然后创建一个POJO类来解析JSON数据。

示例POJO类:

  public class AppGeneralSettings {
    @SerializedName("key1")
String data;


    public String getData() {
        return data;
    }

}
  • 要解析来自互联网的json字符串,请使用此代码段

    AppGeneralSettings data=new Gson().fromJson(jsonString, AppGeneralSettings.class);
    

然后添加一个辅助类来存储和从首选项中检索JSON数据。

示例:用于存储数据的助手类

public class AppPreference {
    private static final String FILE_NAME = BuildConfig.APPLICATION_ID + ".apppreference";
    private static final String APP_GENERAL_SETTINGS = "app_general_settings";
    private final SharedPreferences preferences;

    public AppPreference(Context context) {
        preferences = context.getSharedPreferences(FILE_NAME, MODE_PRIVATE);
    }

    public SharedPreferences.Editor setGeneralSettings(AppGeneralSettings appGeneralSettings) {
        return preferences.edit().putString(APP_GENERAL_SETTINGS, new Gson().toJson(appGeneralSettings));
    }

    public AppGeneralSettings getGeneralSettings() {
        return new Gson().fromJson(preferences.getString(APP_GENERAL_SETTINGS, "{}"), AppGeneralSettings.class);
    }
}

保存数据

new AppPreference().setGeneralSettings(appGeneralSettings).commit();

检索数据

 AppGeneralSettings appGeneralSettings = new AppPreference().getGeneralSettings();

答案 6 :(得分:0)

您可以缓存您的Retrofit响应,因此,当您第二次发出相同请求时,Retrofit将从缓存中获取该请求: https://medium.com/@coreflodev/understand-offline-first-and-offline-last-in-android-71191e92b426https://futurestud.io/tutorials/retrofit-2-activate-response-caching-etag-last-modified。之后,您需要再次解析该json