博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一种简单粗暴的数据层网络缓存
阅读量:6587 次
发布时间:2019-06-24

本文共 4844 字,大约阅读时间需要 16 分钟。

先贴出代码:

1 package com.cache;  2    3 import android.content.Context;  4 import android.text.TextUtils;  5 import android.util.Log;  6    7 import com.google.gson.Gson;  8    9 import java.util.ArrayList; 10 import java.util.List; 11 import java.util.concurrent.CopyOnWriteArrayList; 12 import java.util.concurrent.ExecutorService; 13 import java.util.concurrent.Executors; 14   15 public class CacheHelper { 16   17     private static final String TAG = "CacheHelper"; 18   19     private static final String SHARED_PREFERENCES_NAME = "web_content_cache"; 20     private static final String STORE_KEY_XXX = "STORE_KEY_XXX"; 21   22     private static final boolean NEED_LIMIT_MAX_CACHE_LENGTH = true; 23     private static final int MAX_CACHE_LENGTH = 500000; 24   25     private static CacheHelper sInstance; 26     private ExecutorService mExecutorService; 27   28     public static synchronized CacheHelper instance() { 29         if (null == sInstance) { 30             sInstance = new CacheHelper(); 31         } 32         return sInstance; 33     } 34   35     private CacheHelper() { 36         mExecutorService = Executors.newSingleThreadExecutor(); 37   38     } 39   40     /** 41      * 缓存某个场景下的数据。 42      * 43      * @param cacheValue 44      */ 45     public synchronized void cacheXXXList(final List
cacheValue) { 46 runCache(cacheValue, STORE_KEY_XXX); 47 } 48 49 /** 50 * 获取某个场景下的数据缓存,回调在工作线程中执行。(如果有UI操作,请注意需要在post回UI线程执行。) 51 * 52 * @param callback 53 */ 54 public synchronized void getCacheXXXList(final CacheXXXCallback callback) { 55 if (null == callback) { 56 return; 57 } 58 // 通过某种全局的Utils得到Context,如果没有这种方法,需要在获取实例的时候传入Context 59 final Context appContext = AppUtils.getContext(); 60 if (null == appContext) { 61 return; 62 } 63 checkThreadPool(); 64 mExecutorService.execute(new Runnable() { 65 @Override 66 public void run() { 67 // 目前使用SharedPreference存储Json String,可以改成文件等其他方式 68 final String cacheStr = appContext.getSharedPreferences(SHARED_PREFERENCES_NAME, 69 Context.MODE_PRIVATE).getString(STORE_KEY_XXX, null); 70 final List
cacheValue = new CopyOnWriteArrayList<>(); 71 if (!TextUtils.isEmpty(cacheStr)) { 72 final Gson gson = new Gson(); 73 final List
jsons = gson.fromJson(cacheStr, List.class); 74 for (String item : jsons) { 75 cacheValue.add(gson.fromJson(item, XXXBean.class)); 76 } 77 } 78 callback.onGetXXXList(cacheValue); 79 } 80 }); 81 } 82 83 public static interface CacheXXXCallback { 84 public void onGetXXXList(List
cacheValue); 85 } 86 87 private
void runCache(final List
list, final String cacheKey) { 88 // 通过某种全局的Utils得到Context,如果没有这种方法,需要在获取实例的时候传入Context 89 final Context appContext = AppUtils.getContext(); 90 if (null == appContext) { 91 return; 92 } 93 if (null == list || list.isEmpty()) { 94 return; 95 } 96 final CopyOnWriteArrayList
copyList = new CopyOnWriteArrayList<>(); 97 copyList.addAll(list); 98 if (copyList.isEmpty()) { 99 return;100 }101 checkThreadPool();102 mExecutorService.execute(new Runnable() {103 @Override104 public void run() {105 final Gson gson = new Gson();106 final ArrayList
jsons = new ArrayList<>();107 for (T t : copyList) {108 jsons.add(gson.toJson(t));109 }110 final String cacheStr = gson.toJson(jsons);111 if (NEED_LIMIT_MAX_CACHE_LENGTH) {112 if (cacheStr.length() > MAX_CACHE_LENGTH) {113 Log.e(TAG, "runCache() : cache value length over max limit.");114 return;115 }116 }117 // 目前使用SharedPreference存储Json String,可以改成文件等其他方式118 appContext.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE)119 .edit().putString(cacheKey, cacheStr).commit();120 }121 });122 }123 124 private void checkThreadPool() {125 if (null == mExecutorService || mExecutorService.isShutdown()126 || mExecutorService.isTerminated()) {127 mExecutorService = Executors.newSingleThreadExecutor();128 }129 }130 }
说明几个地方:
(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在这个场景的使用,稍后有时间会有另一篇文章细聊。存储方式可以替换成文件等,只要将读写操作稍作抽象即可,不影响数据转化的逻辑。

转载地址:http://mjhno.baihongyu.com/

你可能感兴趣的文章
区块链共识问题都有什么?
查看>>
分布式事务中间件 Fescar - 全局写排它锁解读
查看>>
Vagrant (一) - 基本知识
查看>>
CSS选择器
查看>>
在 CentOS 7 上搭建 Jenkins + Maven + Git 持续集成环境
查看>>
一星期的学习
查看>>
Javascript 闭包详解
查看>>
数据结构与算法 | Leetcode 19. Remove Nth Node From End of List
查看>>
一起来读you don't know javascript(一)
查看>>
[LeetCode] 862. Shortest Subarray with Sum at Least K
查看>>
BIO、伪异步 IO、AIO和NIO
查看>>
【分享】终端命令工具 自动生成vue组件文件以及修改router.js
查看>>
吴恩达机器学习笔记-非监督学习
查看>>
《从0到1学习Flink》—— 如何自定义 Data Source ?
查看>>
分布式系统关注点——如何去实施「负载均衡」?
查看>>
Div层悬浮实现HTML5 Canvas背景动画
查看>>
技术和商业的碰撞,谈阿里云与天猫双11这十年
查看>>
mysql并发replace死锁
查看>>
[LeetCode] Student Attendance Record I
查看>>
PHP回顾之多进程编程
查看>>