Java 如何缓存 Json 数据以供离线使用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21460461/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 08:50:18  来源:igfitidea点击:

How to Cache Json data to be available offline?

javaandroidjsonoffline

提问by user3241084

I have parsed the JSON Data in a listviewand now I want to make it available offline. Is there a way to save the JSON data at the phone so that you can see the data if your phone is offline?

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

Does someone knows an example?

有人知道一个例子吗?

EDIT works now:

编辑现在工作:

 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;
    }
}

采纳答案by osayilgan

You have two ways. Either you create a database and save all of the data there and retrieve it back when you want to. Or if the data you have is not that much and you don't want to deal with databases, then you write the json string to a text file in the memory card and read it later when you are offline.

你有两种方法。您可以创建一个数据库并将所有数据保存在那里,并在需要时将其取回。或者如果你手头的数据不多,又不想和数据库打交道,那你把json字符串写到内存卡中的一个文本文件中,待离线时再读取。

And for the second case, every time you go online, you can retrieve the same json from your web service and over write it to the old one. This way you can be sure that you have the latest json saved to the device.

对于第二种情况,每次上网时,您都可以从 Web 服务中检索相同的 json 并将其覆盖到旧的。通过这种方式,您可以确保将最新的 json 保存到设备中。

回答by Javier Salinas

Once you download the data you could persist the data on the mobile, using a database or a system of your preference.

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

You can check the different options here: data-storage

您可以在此处查看不同的选项:数据存储

回答by Emil Adz

You can use those two methods two store you JSONfile as a string in your SharedPreferencesand retrieve it back:

您可以使用这两种方法将您的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);
    }
}

Just use setStringProperty("json", "yourJsonString")to save and getStringProperty("json")to retrieve.

仅用于setStringProperty("json", "yourJsonString")保存和 getStringProperty("json")检索。

回答by Mohamed ALOUANE

using SharedPreferences should be prepared to sqlite (unless of course you have a database structure). For caching and storing data pulled from the internet, I recommend robospice: https://github.com/octo-online/robospice. It's a very well done library, easy to use, and should be used any time you download data from the internet or have a long-running task.

使用SharedPreferences 应该准备sqlite(当然除非你有数据库结构)。为了缓存和存储从互联网上提取的数据,我推荐 robospice:https: //github.com/octo-online/robospice。这是一个非常出色的库,易于使用,并且应该在您从 Internet 下载数据或执行长时间运行的任务时使用。

回答by Ashkan Ghodrat

this class will help you cache strings in files with a key to retrieve later on. the string can be a json string and key can be the url you requested and also an identifier for the url if you are using post method.

此类将帮助您使用密钥将字符串缓存在文件中以供稍后检索。字符串可以是 json 字符串,键可以是您请求的 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 "";
}
}

how to use it :

如何使用它 :

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

回答by Darish

How to Cache Json data to be available offline?

如何缓存 Json 数据以供离线使用?

You can use gson to parse JSON data more easily. In your build.gradle file add this dependency.

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

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

Then create a POJO class to parse JSON data.

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

Example POJO class:

示例 POJO 类:

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


    public String getData() {
        return data;
    }

}
  • To parse a json string from internet use this snippet

    AppGeneralSettings data=new Gson().fromJson(jsonString, AppGeneralSettings.class);
    
  • 要解析来自互联网的 json 字符串,请使用此代码段

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

Then add a helper class to store and retrieve JSON data to and from preferences.

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

Example: Helper class to store data

示例:存储数据的助手类

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);
    }
}

To save data

保存数据

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

To retrieve data

检索数据

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

回答by Evgenii Vorobei

You can cache your Retrofit responses, so when you make the same request second time, Retrofit will take it from it's cache: https://medium.com/@coreflodev/understand-offline-first-and-offline-last-in-android-71191e92b426, https://futurestud.io/tutorials/retrofit-2-activate-response-caching-etag-last-modified. After that you'l need to parse that json again

您可以缓存您的 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