【问题标题】:How to Cache Json data to be available offline?如何缓存 Json 数据以供离线使用?
【发布时间】:2014-02-22 23:45:59
【问题描述】:

我已经解析了 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;
    }
}

【问题讨论】:

  • 您可以将其保存到手机数据库中。搜索它。

标签: java android json offline


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    这个类将帮助您将字符串缓存在文件中,并带有一个稍后检索的键。字符串可以是 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!'
    

    【讨论】:

    • 你能告诉我如何使用这个类吗?
    • @BhoomiZalavadiya 我编辑了答案,现在可以使用了!请报告您可能遇到的任何错误。
    【解决方案3】:

    如何缓存 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 字符串,请使用这个 sn-p

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

    【讨论】:

    • 使用 gson 是个好主意,sharedPreferences 也可以工作,但如果 json 结果很大,最好将它们各自保存在不同的文件中。
    【解决方案4】:

    您可以使用这两种方法将您的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") 检索。

    【讨论】:

      【解决方案5】:

      使用 SharedPreferences 应该准备好 sqlite(当然除非你有数据库结构)。对于缓存和存储从 Internet 提取的数据,我推荐使用 robospice:https://github.com/octo-online/robospice。这是一个做得非常好的库,易于使用,任何时候从 Internet 下载数据或有长时间运行的任务都应该使用它。

      【讨论】:

        【解决方案6】:

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

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

        【讨论】:

          【解决方案7】:

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

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

          【讨论】:

          • 取决于 JSON(如果是几个条目),@user3241084 可以使用SharedPreferences
          • @YordanLyubenov 考虑到用户希望在离线时以编程方式存储 JSON 对象,我认为这不仅仅是几个条目。
          • 如何将其添加到我的代码中?我刚试过但没有任何效果?
          • @user3241084 在此处发布您的尝试
          • @user3241084 在互联网上很容易找到它。只需搜索“如何在 android 中读取/写入文件”。我找到了这个链接,它应该可以工作。 stackoverflow.com/questions/14376807/…
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-08-25
          • 1970-01-01
          • 1970-01-01
          • 2013-06-14
          • 2016-06-07
          • 1970-01-01
          相关资源
          最近更新 更多