一种简单粗暴的数据层网络缓存(二)实现方案
2016-11-07 19:56
260 查看
先贴出代码:
说明几个地方:
(1)在helper类内部用线程池实现了异步。使用异步的原因第一,存储Json String的方式有可能是文件,有可能是SharedPreference,涉及到IO;第二,可能会频繁调用写cache和读cache,异步化可以降低调用线程的压力,另外在单一的工作线程(单一线程的线程池)中顺序执行读、写,实现同步。
(2)通过测试发现,对于数据实体对象,Gson无法将对象的List直接转成Json字符串,但大多数的应用场景都是List,所以采用先将List中的每一个对象转成Json String,组成一个List<String>,然后再将List<String>转成一个Json String,存储。在读缓存的时候,是以上过程的逆过程,先将存储的Json String转成List<String>,然后将List中的每一个String转成一个数据实体对象。
(3)存储的方式目前使用的是SharedPreference。关于SharedPreference在这个场景的使用,稍后有时间会有另一篇文章细聊。存储方式可以替换成文件等,只要将读写操作稍作抽象即可,不影响数据转化的逻辑。
package com.cache; import android.content.Context; import android.text.TextUtils; import android.util.Log; import com.google.gson.Gson; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class CacheHelper { private static final String TAG = "CacheHelper"; private static final String SHARED_PREFERENCES_NAME = "web_content_cache"; private static final String STORE_KEY_XXX = "STORE_KEY_XXX"; private static final boolean NEED_LIMIT_MAX_CACHE_LENGTH = true; private static final int MAX_CACHE_LENGTH = 500000; private static CacheHelper sInstance; private ExecutorService mExecutorService; public static synchronized CacheHelper instance() { if (null == sInstance) { sInstance = new CacheHelper(); } return sInstance; } private CacheHelper() { mExecutorService = Executors.newSingleThreadExecutor(); } /** * 缓存某个场景下的数据。 * * @param cacheValue */ public synchronized void cacheXXXList(final List<XXXBean> cacheValue) { runCache(cacheValue, STORE_KEY_XXX); } /** * 获取某个场景下的数据缓存,回调在工作线程中执行。(如果有UI操作,请注意需要在post回UI线程执行。) * * @param callback */ public synchronized void getCacheXXXList(final CacheXXXCallback callback) { if (null == callback) { return; } // 通过某种全局的Utils得到Context,如果没有这种方法,需要在获取实例的时候传入Context final Context appContext = AppUtils.getContext(); if (null == appContext) { return; } checkThreadPool(); mExecutorService.execute(new Runnable() { @Override public void run() { // 目前使用SharedPreference存储Json String,可以改成文件等其他方式 final String cacheStr = appContext.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE).getString(STORE_KEY_XXX, null); final List<XXXBean> cacheValue = new CopyOnWriteArrayList<>(); if (!TextUtils.isEmpty(cacheStr)) { final Gson gson = new Gson(); final List<String> jsons = gson.fromJson(cacheStr, List.class); for (String item : jsons) { cacheValue.add(gson.fromJson(item, XXXBean.class)); } } callback.onGetXXXList(cacheValue); } }); } public static interface CacheXXXCallback { public void onGetXXXList(List<XXXBean> cacheValue); } private <T> void runCache(final List<T> list, final String cacheKey) { // 通过某种全局的Utils得到Context,如果没有这种方法,需要在获取实例的时候传入Context final Context appContext = AppUtils.getContext(); if (null == appContext) { return; } if (null == list || list.isEmpty()) { return; } final CopyOnWriteArrayList<T> copyList = new CopyOnWriteArrayList<>(); copyList.addAll(list); if (copyList.isEmpty()) { return; } checkThreadPool(); mExecutorService.execute(new Runnable() { @Override public void run() { final Gson gson = new Gson(); final ArrayList<String> jsons = new ArrayList<>(); for (T t : copyList) { jsons.add(gson.toJson(t)); } final String cacheStr = gson.toJson(jsons); if (NEED_LIMIT_MAX_CACHE_LENGTH) { if (cacheStr.length() > MAX_CACHE_LENGTH) { Log.e(TAG, "runCache() : cache value length over max limit."); return; } } // 目前使用SharedPreference存储Json String,可以改成文件等其他方式 appContext.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE) .edit().putString(cacheKey, cacheStr).commit(); } }); } private void checkThreadPool() { if (null == mExecutorService || mExecutorService.isShutdown() || mExecutorService.isTerminated()) { mExecutorService = Executors.newSingleThreadExecutor(); } } }
说明几个地方:
(1)在helper类内部用线程池实现了异步。使用异步的原因第一,存储Json String的方式有可能是文件,有可能是SharedPreference,涉及到IO;第二,可能会频繁调用写cache和读cache,异步化可以降低调用线程的压力,另外在单一的工作线程(单一线程的线程池)中顺序执行读、写,实现同步。
(2)通过测试发现,对于数据实体对象,Gson无法将对象的List直接转成Json字符串,但大多数的应用场景都是List,所以采用先将List中的每一个对象转成Json String,组成一个List<String>,然后再将List<String>转成一个Json String,存储。在读缓存的时候,是以上过程的逆过程,先将存储的Json String转成List<String>,然后将List中的每一个String转成一个数据实体对象。
(3)存储的方式目前使用的是SharedPreference。关于SharedPreference在这个场景的使用,稍后有时间会有另一篇文章细聊。存储方式可以替换成文件等,只要将读写操作稍作抽象即可,不影响数据转化的逻辑。
相关文章推荐
- 一种简单粗暴的数据层网络缓存(一)
- Android 网络电台的一种实现方案
- 网络编程资料总结(四)----一种基于UDP协议实现P2P智能穿越NAT的方案
- Android网络电台的一种实现方案
- Android网络电台的一种实现方案(歌醉原创)
- Udp打洞,判断Nat网络类型-一种基于UDP协议实现P2P智能穿越NAT的方案
- lucene的缓存机制和实现方案
- 一种高性能Hierarchical RBAC实现方案
- 一种基于UDP协议实现P2P智能穿越NAT的方案
- samba结合AD实现大型网络方案 推荐
- PHP中插件机制的一种实现方案
- 网络游戏中,玩家数据同步的一种简单实现
- PHP中插件机制的一种实现方案
- 利用Windows的命令行工具tasklist和findstr,start结合计划任务实现一种进程监控的方案
- 网络积件方案(实现篇)
- 一种简单的实现多线程断点续传的方案
- PHP中插件机制的一种实现方案
- 手机客户端网络加速技术方案实现思考
- ICMP协议规范:一种用于网络管理的协议。对照它您可以想一想PING命令实现的机理
- 主规范H.264编解码器:针对消费电子应用的一种低功耗实现方案