├── .gitignore ├── LazyCache ├── .gitignore ├── build.gradle └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── robin │ │ └── lazy │ │ └── cache │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── robin │ │ │ └── lazy │ │ │ └── cache │ │ │ ├── Cache.java │ │ │ ├── CacheLoaderConfiguration.java │ │ │ ├── CacheLoaderManager.java │ │ │ ├── LimitedAge.java │ │ │ ├── LoadCacheTask.java │ │ │ ├── disk │ │ │ ├── DiskCache.java │ │ │ ├── impl │ │ │ │ ├── BaseDiskCache.java │ │ │ │ ├── LimitedAgeDiskCache.java │ │ │ │ ├── LimitedAgePropertiesConfig.java │ │ │ │ └── ext │ │ │ │ │ ├── DiskLruCache.java │ │ │ │ │ ├── LruDiskCache.java │ │ │ │ │ ├── StrictLineReader.java │ │ │ │ │ └── Util.java │ │ │ ├── naming │ │ │ │ ├── FileNameGenerator.java │ │ │ │ ├── HashCodeFileNameGenerator.java │ │ │ │ └── Md5FileNameGenerator.java │ │ │ ├── read │ │ │ │ ├── BitmapReadFromDisk.java │ │ │ │ ├── BytesReadFromDisk.java │ │ │ │ ├── InputStreamReadFormDisk.java │ │ │ │ ├── ReadFromDisk.java │ │ │ │ ├── SerializableReadFromDisk.java │ │ │ │ └── StringReadFromDisk.java │ │ │ └── write │ │ │ │ ├── BitmapWriteInDisk.java │ │ │ │ ├── BytesWriteInDisk.java │ │ │ │ ├── InputStreamWriteInDisk.java │ │ │ │ ├── SerializableWriteInDisk.java │ │ │ │ ├── StringWriteInDisk.java │ │ │ │ └── WriteInDisk.java │ │ │ ├── entity │ │ │ ├── CacheGetEntity.java │ │ │ └── CachePutEntity.java │ │ │ ├── memory │ │ │ ├── EntryRemovedProcess.java │ │ │ ├── MemoryCache.java │ │ │ ├── SizeOfCacheCalculator.java │ │ │ └── impl │ │ │ │ ├── EntryRemovedProcessMemoryCache.java │ │ │ │ ├── FuzzyKeyMemoryCache.java │ │ │ │ ├── LimitedAgeMemoryCache.java │ │ │ │ ├── LruMemoryCache.java │ │ │ │ ├── SizeOfMemoryCache.java │ │ │ │ └── ext │ │ │ │ └── LruCache.java │ │ │ ├── process │ │ │ ├── CacheDataProcess.java │ │ │ └── DefaultCacheDataProcess.java │ │ │ └── util │ │ │ ├── DiskCacheUtils.java │ │ │ ├── MemoryCacheUtils.java │ │ │ └── log │ │ │ ├── AndroidLog.java │ │ │ ├── CacheLog.java │ │ │ └── ILog.java │ └── res │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── robin │ └── lazy │ └── cache │ └── ExampleUnitTest.java ├── README.md ├── Sample ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── robin │ │ └── lazy │ │ └── sample │ │ ├── ApplicationTest.java │ │ └── MainActivityTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ └── province.json │ ├── java │ │ └── com │ │ │ └── robin │ │ │ └── lazy │ │ │ └── sample │ │ │ ├── App.java │ │ │ ├── FileUtil.java │ │ │ └── MainActivity.java │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── robin │ └── lazy │ └── sample │ ├── Calculator.java │ ├── CalculatorTest.java │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # files for the dex VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Local configuration file (sdk path, etc) 12 | local.properties 13 | 14 | # Eclipse project files 15 | .classpath 16 | .project 17 | 18 | # Proguard folder generated by Eclipse 19 | proguard/ 20 | 21 | # Intellij project files 22 | *.iml 23 | *.ipr 24 | *.iws 25 | .idea/ 26 | 27 | # files for buile 28 | /build 29 | /.gradle 30 | #/gradle 31 | #gradlew 32 | #gradlew.bat 33 | #gradle.properties 34 | #README.md 35 | 36 | -------------------------------------------------------------------------------- /LazyCache/.gitignore: -------------------------------------------------------------------------------- 1 | # built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # files for the dex VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | 12 | # Intellij project files 13 | *.iml 14 | *.pro 15 | 16 | # files for buile 17 | /build 18 | 19 | # signing files 20 | release.keystore -------------------------------------------------------------------------------- /LazyCache/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 33 5 | 6 | defaultConfig { 7 | minSdkVersion 9 8 | targetSdkVersion 33 9 | versionCode 112 10 | versionName "1.1.2" 11 | } 12 | 13 | lintOptions { 14 | abortOnError false 15 | } 16 | 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | } 24 | 25 | dependencies { 26 | api fileTree(include: ['*.jar'], dir: 'libs') 27 | api 'com.github.Robin-jiangyufeng:LazyUtilForAndroid:1.1.6' 28 | testImplementation 'junit:junit:4.12' 29 | } 30 | 31 | // 为注释中文提供解决方案 32 | tasks.withType(JavaCompile) { 33 | options.encoding = "UTF-8" 34 | } 35 | -------------------------------------------------------------------------------- /LazyCache/src/androidTest/java/com/robin/lazy/cache/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.robin.lazy.cache; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /LazyCache/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/Cache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: Cache.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2015年12月11日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache; 13 | /** 14 | * 缓存接口 15 | * 16 | * @author jiangyufeng 17 | * @version [版本号, 2015年12月11日] 18 | * @see [相关类/方法] 19 | * @since [产品/模块版本] 20 | */ 21 | public interface Cache { 22 | 23 | /** 24 | * Puts value into cache by key 25 | * @param 26 | * 27 | * @return true - if value was put into cache successfully, false - if value was not put into 28 | * cache 29 | */ 30 | boolean put(String key, V value); 31 | 32 | /** 33 | * Puts value into cache by key 34 | * @param 35 | *@param maxLimitTime 内存缓存数据的有效期(单位秒) 36 | * @return true - if value was put into cache successfully, false - if value was not put into 37 | * cache 38 | */ 39 | boolean put(String key, V value, long maxLimitTime); 40 | 41 | /** 42 | * Returns value by key. If there is no value for key then null will be returned. 43 | * @param */ 44 | V get(String keyk); 45 | 46 | /** Removes item by key */ 47 | boolean remove(String key); 48 | 49 | /*** 50 | * 重置内存缓存的最大限度大小 51 | * @param maxSize 52 | * void 53 | * @throws 54 | * @see [类、类#方法、类#成员] 55 | */ 56 | void resize(int maxSize); 57 | 58 | /** 59 | * 关闭缓存,关闭后不能再使用此缓存 60 | * void 61 | * @throws 62 | * @see [类、类#方法、类#成员] 63 | */ 64 | void close(); 65 | 66 | /*** 67 | * 清理掉当前缓存,对象完全被清理 68 | * void 69 | * @throws 70 | * @see [类、类#方法、类#成员] 71 | */ 72 | void clear(); 73 | } 74 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/CacheLoaderConfiguration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: CacheLoadConfiguration.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2015年12月15日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache; 13 | 14 | import android.content.Context; 15 | 16 | import com.robin.lazy.cache.disk.DiskCache; 17 | import com.robin.lazy.cache.disk.impl.LimitedAgeDiskCache; 18 | import com.robin.lazy.cache.disk.naming.FileNameGenerator; 19 | import com.robin.lazy.cache.memory.MemoryCache; 20 | import com.robin.lazy.cache.memory.impl.LimitedAgeMemoryCache; 21 | import com.robin.lazy.cache.util.DiskCacheUtils; 22 | 23 | /** 24 | * 缓存加载配置 25 | * 26 | * @author jiangyufeng 27 | * @version [版本号, 2015年12月15日] 28 | * @see [相关类/方法] 29 | * @since [产品/模块版本] 30 | */ 31 | public class CacheLoaderConfiguration { 32 | 33 | /** 34 | * 磁盘缓存类 35 | */ 36 | private DiskCache diskCache; 37 | 38 | /*** 39 | * 内存缓存类 40 | */ 41 | private MemoryCache memoryCache; 42 | 43 | /** 缓存有效期(单位分钟) */ 44 | private long maxAge ; 45 | 46 | /** 47 | * 48 | * @param diskCacheFileNameGenerator 49 | * @param diskCacheSize 磁盘缓存大小 (单位字节byte) 50 | * @param diskCacheFileCount 磁盘缓存文件的最大限度 51 | * @param memoryCache 内存缓存 52 | * @param maxAge 有效期(单位分钟) 53 | */ 54 | public CacheLoaderConfiguration(Context context, 55 | FileNameGenerator diskCacheFileNameGenerator, long diskCacheSize, 56 | int diskCacheFileCount, MemoryCache memoryCache, long maxAge) { 57 | this(context, diskCacheFileNameGenerator, diskCacheSize, 58 | diskCacheFileCount, memoryCache); 59 | this.maxAge = maxAge; 60 | } 61 | 62 | /** 63 | * <默认构造函数> 64 | * 65 | * @param diskCacheFileNameGenerator 66 | * @param diskCacheSize 磁盘缓存大小(单位字节byte) 67 | * @param diskCacheFileCount 磁盘缓存文件的最大限度 68 | * @param memoryCache 内存缓存 69 | */ 70 | public CacheLoaderConfiguration(Context context, 71 | FileNameGenerator diskCacheFileNameGenerator, long diskCacheSize, 72 | int diskCacheFileCount, MemoryCache memoryCache) { 73 | diskCache = DiskCacheUtils.createDiskCache(context, 74 | diskCacheFileNameGenerator, diskCacheSize, diskCacheFileCount); 75 | this.memoryCache = memoryCache; 76 | } 77 | 78 | /*** 79 | * 获取基本类型的磁盘缓存 80 | * 81 | * @return DiskCache 82 | * @throws 83 | * @see [类、类#方法、类#成员] 84 | */ 85 | public DiskCache getDiskCache() { 86 | return diskCache; 87 | } 88 | 89 | /** 90 | * 获取有缓存有有限期的磁盘缓存 91 | * 92 | * @return DiskCache 93 | * @throws 94 | * @see [类、类#方法、类#成员] 95 | */ 96 | public DiskCache getLimitAgeDiskCache() { 97 | return new LimitedAgeDiskCache(diskCache, maxAge * 60); 98 | } 99 | 100 | /*** 101 | * 设置磁盘缓存 102 | * 103 | * @param diskCache 104 | * @throws 105 | * @see [类、类#方法、类#成员] 106 | */ 107 | public void setDiskCache(DiskCache diskCache) { 108 | this.diskCache = diskCache; 109 | } 110 | 111 | /*** 112 | * 获取基本类型内存缓存 113 | * 114 | * @return MemoryCache 115 | * @throws 116 | * @see [类、类#方法、类#成员] 117 | */ 118 | public MemoryCache getMemoryCache() { 119 | return memoryCache; 120 | } 121 | 122 | /*** 123 | * 获取缓存有过期时间的缓存加载工具 124 | * 125 | * @return MemoryCache 126 | * @throws 127 | * @see [类、类#方法、类#成员] 128 | */ 129 | public MemoryCache getLimitedAgeMemoryCache() { 130 | return new LimitedAgeMemoryCache(memoryCache, maxAge * 60); 131 | } 132 | 133 | /*** 134 | * 设置内存缓存 135 | * 136 | * @param memoryCache 137 | * @throws 138 | * @see [类、类#方法、类#成员] 139 | */ 140 | public void setMemoryCache(MemoryCache memoryCache) { 141 | this.memoryCache = memoryCache; 142 | } 143 | 144 | /** 145 | * 清理 void 146 | * 147 | * @throws 148 | * @see [类、类#方法、类#成员] 149 | */ 150 | public void close() { 151 | if (diskCache != null) { 152 | diskCache.close(); 153 | diskCache = null; 154 | } 155 | if (memoryCache != null) { 156 | memoryCache.close(); 157 | memoryCache = null; 158 | } 159 | } 160 | 161 | 162 | } 163 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/CacheLoaderManager.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: CacheLoadManager.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2015年12月15日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache; 13 | 14 | import android.content.Context; 15 | import android.graphics.Bitmap; 16 | 17 | import com.robin.lazy.cache.disk.naming.FileNameGenerator; 18 | import com.robin.lazy.cache.disk.read.BitmapReadFromDisk; 19 | import com.robin.lazy.cache.disk.read.BytesReadFromDisk; 20 | import com.robin.lazy.cache.disk.read.InputStreamReadFormDisk; 21 | import com.robin.lazy.cache.disk.read.SerializableReadFromDisk; 22 | import com.robin.lazy.cache.disk.read.StringReadFromDisk; 23 | import com.robin.lazy.cache.disk.write.BitmapWriteInDisk; 24 | import com.robin.lazy.cache.disk.write.BytesWriteInDisk; 25 | import com.robin.lazy.cache.disk.write.InputStreamWriteInDisk; 26 | import com.robin.lazy.cache.disk.write.SerializableWriteInDisk; 27 | import com.robin.lazy.cache.disk.write.StringWriteInDisk; 28 | import com.robin.lazy.cache.entity.CacheGetEntity; 29 | import com.robin.lazy.cache.entity.CachePutEntity; 30 | import com.robin.lazy.cache.memory.MemoryCache; 31 | import com.robin.lazy.cache.util.MemoryCacheUtils; 32 | import com.robin.lazy.cache.util.log.CacheLog; 33 | import com.robin.lazy.util.IoUtils; 34 | import com.robin.lazy.util.bitmap.ImageDecodingInfo; 35 | 36 | import java.io.InputStream; 37 | import java.io.Serializable; 38 | 39 | /** 40 | * 缓存加载管理者 41 | * 42 | * @author jiangyufeng 43 | * @version [版本号, 2015年12月15日] 44 | * @see [相关类/方法] 45 | * @since [产品/模块版本] 46 | */ 47 | public class CacheLoaderManager { 48 | private final static String LOG_TAG=CacheLoaderManager.class.getSimpleName(); 49 | private volatile static CacheLoaderManager instance; 50 | 51 | private CacheLoaderConfiguration cacheLoaderConfiguration; 52 | 53 | /** 基础的缓存加载任务 */ 54 | protected LoadCacheTask cacheTask; 55 | 56 | /** Returns singleton class instance */ 57 | public static CacheLoaderManager getInstance() { 58 | if (instance == null) { 59 | synchronized (CacheLoaderManager.class) { 60 | if (instance == null) { 61 | instance = new CacheLoaderManager(); 62 | } 63 | } 64 | } 65 | return instance; 66 | } 67 | 68 | private CacheLoaderManager() { 69 | 70 | } 71 | 72 | /*** 73 | * 初始化缓存的一些配置 74 | * 75 | * @param diskCacheFileNameGenerator 76 | * @param diskCacheSize 磁盘缓存大小 77 | * @param diskCacheFileCount 磁盘缓存文件的最大限度 78 | * @param maxMemorySize 内存缓存的大小 79 | * @return CacheLoaderConfiguration 80 | * @throws 81 | * @see [类、类#方法、类#成员] 82 | */ 83 | public void init(Context context,FileNameGenerator diskCacheFileNameGenerator, long diskCacheSize, 84 | int diskCacheFileCount, int maxMemorySize) { 85 | if (this.cacheLoaderConfiguration != null) { 86 | this.cacheLoaderConfiguration.close(); 87 | this.cacheLoaderConfiguration = null; 88 | } 89 | MemoryCache memoryCache= MemoryCacheUtils.createLruMemoryCache(maxMemorySize); 90 | cacheLoaderConfiguration = new CacheLoaderConfiguration(context, 91 | diskCacheFileNameGenerator, diskCacheSize, diskCacheFileCount, 92 | memoryCache); 93 | cacheTask = new LoadCacheTask( 94 | cacheLoaderConfiguration.getLimitAgeDiskCache(), 95 | cacheLoaderConfiguration.getLimitedAgeMemoryCache()); 96 | } 97 | 98 | /** 99 | * 初始化缓存配置 100 | * 101 | * @param cacheLoaderConfiguration 102 | * @return CacheLoaderConfiguration 103 | * @throws 104 | * @see [类、类#方法、类#成员] 105 | */ 106 | public void init(CacheLoaderConfiguration cacheLoaderConfiguration) { 107 | if (this.cacheLoaderConfiguration != null) { 108 | this.cacheLoaderConfiguration.close(); 109 | this.cacheLoaderConfiguration = null; 110 | } 111 | this.cacheLoaderConfiguration = cacheLoaderConfiguration; 112 | cacheTask = new LoadCacheTask( 113 | cacheLoaderConfiguration.getLimitAgeDiskCache(), 114 | cacheLoaderConfiguration.getLimitedAgeMemoryCache()); 115 | } 116 | 117 | /*** 118 | * 加载缓存中对应的字节数组 119 | * @param key 120 | * @return 121 | * byte[] 122 | * @throws 123 | * @see [类、类#方法、类#成员] 124 | */ 125 | public byte[] loadBytes(String key){ 126 | if(!isInitialize()) 127 | return null; 128 | CacheGetEntity cacheGetEntity=new CacheGetEntity(new BytesReadFromDisk()); 129 | return cacheTask.query(key, cacheGetEntity); 130 | } 131 | 132 | /** 133 | * 加载Bitmap 134 | * @param key 135 | * @return 136 | * Bitmap 137 | * @throws 138 | * @see [类、类#方法、类#成员] 139 | */ 140 | public Bitmap loadBitmap(String key,ImageDecodingInfo imageDecodingInfo){ 141 | if(!isInitialize()) 142 | return null; 143 | CacheGetEntity cacheGetEntity=new CacheGetEntity(new BitmapReadFromDisk(imageDecodingInfo)); 144 | return cacheTask.query(key, cacheGetEntity); 145 | } 146 | 147 | /** 148 | * 加载String 149 | * @param key 150 | * @return 等到缓存数据 151 | * String 152 | * @throws 153 | * @see [类、类#方法、类#成员] 154 | */ 155 | public String loadString(String key){ 156 | if(!isInitialize()) 157 | return null; 158 | CacheGetEntity cacheGetEntity=new CacheGetEntity(new StringReadFromDisk()); 159 | return cacheTask.query(key, cacheGetEntity); 160 | } 161 | 162 | /** 163 | * 获取Serializable 164 | * @param key 165 | * @return 166 | * Serializable 167 | * @throws 168 | * @see [类、类#方法、类#成员] 169 | */ 170 | public V loadSerializable(String key){ 171 | if(!isInitialize()) 172 | return null; 173 | CacheGetEntity cacheGetEntity=new CacheGetEntity( 174 | new SerializableReadFromDisk()); 175 | return cacheTask.query(key, cacheGetEntity); 176 | } 177 | 178 | /** 179 | * 加载InputStream 180 | * @param key 181 | * @return 182 | * InputStream 183 | * @throws 184 | * @see [类、类#方法、类#成员] 185 | */ 186 | public InputStream loadInputStream(String key){ 187 | if(!isInitialize()) 188 | return null; 189 | CacheGetEntity cacheGetEntity=new CacheGetEntity( 190 | new InputStreamReadFormDisk()); 191 | return cacheTask.query(key, cacheGetEntity); 192 | } 193 | 194 | /** 195 | * save bytes到缓存 196 | * @param key 197 | * @param value 198 | * @param maxLimitTime 缓存期限(单位分钟,小于等于0表示永久) 199 | * @return 200 | * boolean 201 | * @throws 202 | * @see [类、类#方法、类#成员] 203 | */ 204 | public boolean saveBytes(String key,byte[] value,long maxLimitTime){ 205 | if(!isInitialize()) 206 | return false; 207 | CachePutEntity cachePutEntity=new CachePutEntity(new BytesWriteInDisk()); 208 | return cacheTask.insert(key, cachePutEntity, value, maxLimitTime * 60); 209 | } 210 | 211 | /** 212 | * save Bitmap到缓存 213 | * @param key 214 | * @param value 215 | * @param maxLimitTime 缓存期限(单位分钟,小于等于0表示永久) 216 | * @param isRecycle 使用玩是否释放回收 217 | * @return 218 | * boolean 219 | * @throws 220 | * @see [类、类#方法、类#成员] 221 | */ 222 | public boolean saveBitmap(String key,Bitmap value,long maxLimitTime,boolean isRecycle){ 223 | if(!isInitialize()) 224 | return false; 225 | CachePutEntity cachePutEntity=new CachePutEntity(new BitmapWriteInDisk(isRecycle)); 226 | return cacheTask.insert(key, cachePutEntity, value, maxLimitTime * 60); 227 | } 228 | 229 | /** 230 | * save String到缓存 231 | * @param key 232 | * @param value 要缓存的值 233 | * @param maxLimitTime 缓存期限(单位分钟,小于等于0表示永久) 234 | * @return 是否保存成功 235 | * boolean 236 | * @throws 237 | * @see [类、类#方法、类#成员] 238 | */ 239 | public boolean saveString(String key,String value,long maxLimitTime){ 240 | if(!isInitialize()) 241 | return false; 242 | CachePutEntity cachePutEntity=new CachePutEntity(new StringWriteInDisk()); 243 | return cacheTask.insert(key, cachePutEntity, value, maxLimitTime * 60); 244 | } 245 | 246 | /** 247 | * save Serializable到缓存 248 | * @param 249 | * @param key 250 | * @param values 251 | * @param maxLimitTime 缓存期限(单位分钟,小于等于0表示永久) 252 | * @return 253 | * boolean 254 | * @throws 255 | * @see [类、类#方法、类#成员] 256 | */ 257 | public boolean saveSerializable(String key,V values,long maxLimitTime){ 258 | if(!isInitialize()) 259 | return false; 260 | CachePutEntity cachePutEntity=new CachePutEntity(new SerializableWriteInDisk()); 261 | return cacheTask.insert(key, cachePutEntity, values, maxLimitTime * 60); 262 | } 263 | 264 | /** 265 | * save inputStream到缓存 266 | * @param key 267 | * @param values 268 | * @param listener 进度监听器 269 | * @param maxLimitTime 缓存期限(单位分钟,小于等于0表示永久) 270 | * @return 271 | */ 272 | public boolean saveInputStream(String key,InputStream values,IoUtils.CopyListener listener,long maxLimitTime){ 273 | if(!isInitialize()) 274 | return false; 275 | CachePutEntity cachePutEntity=new CachePutEntity( 276 | new InputStreamWriteInDisk(listener)); 277 | return cacheTask.insert(key, cachePutEntity, values, maxLimitTime * 60); 278 | } 279 | 280 | 281 | /*** 282 | * 删除一条缓存数据 283 | * 284 | * @param key 数据标识 285 | * @return 是否删除成功 boolean 286 | * @throws 287 | * @see [类、类#方法、类#成员] 288 | */ 289 | public boolean delete(String key) { 290 | if(!isInitialize()) 291 | return false; 292 | return cacheTask.delete(key); 293 | } 294 | 295 | /** 296 | * 获取缓存大小 297 | * @return 298 | * long 299 | * @throws 300 | * @see [类、类#方法、类#成员] 301 | */ 302 | public long size(){ 303 | if(!isInitialize()) 304 | return 0; 305 | return cacheTask.size(); 306 | } 307 | 308 | /** 309 | * 是否初始化 310 | * @return 311 | * boolean 312 | * @throws 313 | * @see [类、类#方法、类#成员] 314 | */ 315 | private boolean isInitialize(){ 316 | if(cacheTask==null){ 317 | CacheLog.e(LOG_TAG,"缓存任务没有初始化"); 318 | return false; 319 | } 320 | return true; 321 | } 322 | 323 | /*** 324 | * 清理掉当前缓存,可以继续使用 325 | * 326 | * @throws 327 | * @see [类、类#方法、类#成员] 328 | */ 329 | public void clear() { 330 | if(cacheTask!=null){ 331 | cacheTask.clear(); 332 | } 333 | } 334 | 335 | /** 336 | * 关闭缓存,关闭后将不能再使用缓存了 337 | * void 338 | * @throws 339 | * @see [类、类#方法、类#成员] 340 | */ 341 | public void close(){ 342 | if(cacheTask!=null){ 343 | cacheTask.close(); 344 | cacheTask = null; 345 | } 346 | if (cacheLoaderConfiguration != null) { 347 | cacheLoaderConfiguration.close(); 348 | cacheLoaderConfiguration = null; 349 | } 350 | if(instance!=null){ 351 | instance = null; 352 | } 353 | } 354 | } 355 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/LimitedAge.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: LimitedAge.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2015年12月15日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache; 13 | /** 14 | * 数据有效时间处理类 15 | * 16 | * @author jiangyufeng 17 | * @version [版本号, 2015年12月15日] 18 | * @see [相关类/方法] 19 | * @since [产品/模块版本] 20 | */ 21 | public class LimitedAge { 22 | /** 保存时候的时间(单位毫秒) */ 23 | private long saveTime; 24 | /** 磁盘缓存文件的最大有效时间(单位秒,如果小于等于0则永久保存) */ 25 | private long maxLimitTime; 26 | 27 | public LimitedAge(long saveTime, long maxLimitTime) { 28 | this.saveTime = saveTime; 29 | this.maxLimitTime = maxLimitTime; 30 | } 31 | 32 | /*** 33 | * 检测是否过期 34 | * 35 | * @return boolean 返回是否过期(为true则过期) 36 | * @throws 37 | * @see [类、类#方法、类#成员] 38 | */ 39 | public boolean checkExpire() { 40 | if(maxLimitTime<=0)return false; 41 | if (System.currentTimeMillis() - saveTime > (maxLimitTime * 1000)) { 42 | return true; 43 | } 44 | return false; 45 | } 46 | 47 | /** 48 | * 计算数据剩余有效时间(单位秒,-1为始终有效) 49 | * @return 50 | * long 51 | * @throws 52 | * @see [类、类#方法、类#成员] 53 | */ 54 | public long limitedTime(){ 55 | return maxLimitTime<=0?-1:(maxLimitTime*1000-(System.currentTimeMillis()-saveTime))/1000; 56 | } 57 | 58 | /*** 59 | * 获取数据保存时的时间(单位毫秒) 60 | * 61 | * @return long 62 | * @throws 63 | * @see [类、类#方法、类#成员] 64 | */ 65 | public long getSaveTime() { 66 | return saveTime; 67 | } 68 | 69 | /*** 70 | * 设置缓数据存时的时间(单位毫秒) 71 | * 72 | * @param saveTime 73 | * void 74 | * @throws 75 | * @see [类、类#方法、类#成员] 76 | */ 77 | public void setSaveTime(long saveTime) { 78 | this.saveTime = saveTime; 79 | } 80 | 81 | /*** 82 | * 获取缓存数据的有效时间(单位秒) 83 | * 84 | * @return long 85 | * @throws 86 | * @see [类、类#方法、类#成员] 87 | */ 88 | public long getMaxLimitTime() { 89 | return maxLimitTime; 90 | } 91 | 92 | /** 93 | * 设置缓存的有效时间(单位秒) 94 | * 95 | * @param maxLimitTime 96 | * void 97 | * @throws 98 | * @see [类、类#方法、类#成员] 99 | */ 100 | public void setMaxLimitTime(long maxLimitTime) { 101 | this.maxLimitTime = maxLimitTime; 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/LoadCacheTask.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: LoadCacheTask.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2015年12月15日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache; 13 | 14 | import android.text.TextUtils; 15 | 16 | import com.robin.lazy.cache.disk.DiskCache; 17 | import com.robin.lazy.cache.disk.impl.LimitedAgeDiskCache; 18 | import com.robin.lazy.cache.entity.CacheGetEntity; 19 | import com.robin.lazy.cache.entity.CachePutEntity; 20 | import com.robin.lazy.cache.memory.MemoryCache; 21 | import com.robin.lazy.cache.process.CacheDataProcess; 22 | import com.robin.lazy.cache.util.log.CacheLog; 23 | 24 | import java.io.File; 25 | import java.io.IOException; 26 | 27 | /** 28 | * 基本的加载缓存任务 29 | * 30 | * @author jiangyufeng 31 | * @version [版本号, 2015年12月15日] 32 | * @see [相关类/方法] 33 | * @since [产品/模块版本] 34 | */ 35 | public class LoadCacheTask { 36 | private final static String LOG_TAG=LoadCacheTask.class.getSimpleName(); 37 | /** 38 | * 磁盘缓存类 39 | */ 40 | private DiskCache diskCache; 41 | 42 | /*** 43 | * 内存缓存类 44 | */ 45 | private MemoryCache memoryCache; 46 | 47 | public LoadCacheTask(DiskCache diskCache, MemoryCache memoryCache) { 48 | this.diskCache = diskCache; 49 | this.memoryCache = memoryCache; 50 | } 51 | 52 | /** 53 | * 插入一条缓存数据 54 | * 55 | * @param key 56 | * @param cachePutEntity 57 | * @param value 要存入缓存的数据 58 | * @return boolean 59 | * @throws 60 | * @see [类、类#方法、类#成员] 61 | */ 62 | public boolean insert(String key, CachePutEntity cachePutEntity,V value) { 63 | return insert(key, cachePutEntity,value, -1); 64 | } 65 | 66 | /*** 67 | * 插入一条缓存数据 68 | * 69 | * @param 70 | * @param key 数据标识 71 | * @param cachePutEntity 72 | * @param value 要存入缓存的数据 73 | * @param insertCacheProcess 对插入的数据进行处理的类(处理后在插入缓存) 74 | * @param maxLimitTime 有效时间(单位秒) 75 | * @return 插入是否成功 boolean 76 | * @throws 77 | * @see [类、类#方法、类#成员] 78 | */ 79 | public boolean insert(String key, CachePutEntity cachePutEntity,V value, 80 | CacheDataProcess insertCacheProcess,long maxLimitTime) { 81 | return insert(key, cachePutEntity,insertCacheProcess.process(value), maxLimitTime); 82 | } 83 | 84 | /*** 85 | * 插入一条缓存数据 86 | * 87 | * @param 88 | * @param key 数据标识 89 | * @param cachePutEntity 90 | * @param value 要存入缓存的数据 91 | * @param maxLimitTime 有效时间(单位秒) 92 | * @return 插入是否成功 boolean 93 | * @throws 94 | * @see [类、类#方法、类#成员] 95 | */ 96 | public boolean insert(String key, CachePutEntity cachePutEntity, 97 | V value, long maxLimitTime) { 98 | if (diskCache == null || memoryCache == null || cachePutEntity == null) { 99 | CacheLog.e(LOG_TAG, 100 | "diskCache or memoryCache or cachePutEntity is null",new NullPointerException()); 101 | return false; 102 | } 103 | boolean isSuccess = false; 104 | try { 105 | // V val = memoryCache.get(key); 106 | // if (val != null) { 107 | // boolean isExist = ObjectUtils.isEquals(val, value);// 判断缓存中是否以存在该数据 108 | // if (isExist) { 109 | // // 当前内存缓存中已经存在这个数据 110 | // return true; 111 | // } else { 112 | // memoryCache.remove(key); 113 | // } 114 | // } 115 | if (maxLimitTime > 0) { 116 | isSuccess = memoryCache.put(key, value, maxLimitTime); 117 | } else { 118 | isSuccess = memoryCache.put(key, value); 119 | } 120 | //以下是磁盘缓存 121 | if(isSuccess){ 122 | File file = diskCache.getFile(key); 123 | if (file != null && file.exists()) { 124 | diskCache.remove(key); 125 | } 126 | if (maxLimitTime > 0) { 127 | isSuccess = diskCache.put(key, cachePutEntity.getWriteInDisk(), 128 | value, maxLimitTime); 129 | } else { 130 | isSuccess = diskCache.put(key, cachePutEntity.getWriteInDisk(), 131 | value); 132 | } 133 | } 134 | } catch (IOException e) { 135 | CacheLog.e(LOG_TAG,"文件写入磁盘失败",e); 136 | } catch (Exception e) { 137 | CacheLog.e(LOG_TAG, "文件写入磁盘失败",e); 138 | } 139 | return isSuccess; 140 | } 141 | 142 | /*** 143 | * 查询一条缓存数据 144 | * 145 | * @param 146 | * @param key 147 | * @param cacheGetEntity 148 | * @param queryDataProcess 对于查询到的数据进行处理的方法(从缓存中取道数据后再进行加工处理后给使用者) 149 | * @return V 150 | * @throws 151 | * @see [类、类#方法、类#成员] 152 | */ 153 | public V query(String key, CacheGetEntity cacheGetEntity,CacheDataProcess queryDataProcess) { 154 | return queryDataProcess.process(query(key, cacheGetEntity)); 155 | } 156 | 157 | /*** 158 | * 查询一条缓存数据 159 | * 160 | * @param 161 | * @param key 162 | * @param cacheGetEntity 163 | * @return V 164 | * @throws 165 | * @see [类、类#方法、类#成员] 166 | */ 167 | public V query(String key, CacheGetEntity cacheGetEntity) { 168 | if (diskCache == null || memoryCache == null || cacheGetEntity == null) { 169 | CacheLog.e(LOG_TAG, 170 | "diskCache or memoryCache or cacheGetEntity is null",new NullPointerException()); 171 | return null; 172 | } 173 | V value = null; 174 | try { 175 | value = memoryCache.get(key); 176 | if (value != null) { 177 | return value; 178 | } 179 | value = diskCache.get(key, cacheGetEntity.getReadFromDisk()); 180 | if (value != null) { 181 | if(diskCache instanceof LimitedAgeDiskCache){ 182 | LimitedAgeDiskCache limitedAgeDiskCache=(LimitedAgeDiskCache)diskCache; 183 | long limitedTime=limitedAgeDiskCache.getLimitedTime(key); 184 | if(limitedTime>0){ 185 | memoryCache.put(key, value, limitedTime); 186 | }else { 187 | memoryCache.put(key, value); 188 | } 189 | }else{ 190 | memoryCache.put(key, value); 191 | } 192 | } 193 | } catch (Exception e) { 194 | CacheLog.e(LOG_TAG, "缓存缓存数据错误",e); 195 | } 196 | return value; 197 | } 198 | 199 | /*** 200 | * 删除一条缓存数据 201 | * 202 | * @param key 数据标识 203 | * @return 是否删除成功 boolean 204 | * @throws 205 | * @see [类、类#方法、类#成员] 206 | */ 207 | public boolean delete(String key) { 208 | if (diskCache == null || memoryCache == null) { 209 | CacheLog.e(LOG_TAG, 210 | "diskCache or memoryCache or cachePutEntity is null",new NullPointerException()); 211 | return false; 212 | } 213 | boolean isSuccess = false; 214 | if (memoryCache.keys().contains(key)) { 215 | isSuccess = memoryCache.remove(key); 216 | } 217 | if (isSuccess) { 218 | File file = diskCache.getFile(key); 219 | if (file != null && file.exists()) { 220 | isSuccess = diskCache.remove(key); 221 | } 222 | } 223 | return isSuccess; 224 | } 225 | 226 | /*** 227 | * 计算缓存大小 228 | * @return 229 | * long 230 | * @throws 231 | * @see [类、类#方法、类#成员] 232 | */ 233 | public long size(){ 234 | if (diskCache == null || memoryCache == null) { 235 | CacheLog.e(LOG_TAG, 236 | "diskCache or memoryCache or cachePutEntity is null",new NullPointerException()); 237 | return 0; 238 | } 239 | String mapString=memoryCache.snapshot().toString(); 240 | long memoryCacheSize = TextUtils.isEmpty(mapString)?0:mapString.getBytes().length; 241 | return diskCache.size()+memoryCacheSize; 242 | } 243 | 244 | public DiskCache getDiskCache() { 245 | return diskCache; 246 | } 247 | 248 | public void setDiskCache(DiskCache diskCache) { 249 | this.diskCache = diskCache; 250 | } 251 | 252 | public MemoryCache getMemoryCache() { 253 | return memoryCache; 254 | } 255 | 256 | public void setMemoryCache(MemoryCache memoryCache) { 257 | this.memoryCache = memoryCache; 258 | } 259 | 260 | /** 261 | * 关闭缓存,对象完全被清理,关闭后不能再使用此缓存 void 262 | * 263 | * @throws 264 | * @see [类、类#方法、类#成员] 265 | */ 266 | public void close() { 267 | if (diskCache != null) { 268 | diskCache.close(); 269 | diskCache = null; 270 | } 271 | if (memoryCache != null) { 272 | memoryCache.close(); 273 | memoryCache = null; 274 | } 275 | } 276 | 277 | /*** 278 | * 清理掉当前缓存 279 | * 280 | * @throws 281 | * @see [类、类#方法、类#成员] 282 | */ 283 | public void clear() { 284 | if (diskCache != null) { 285 | diskCache.clear(); 286 | } 287 | if (memoryCache != null) { 288 | memoryCache.clear(); 289 | } 290 | } 291 | 292 | } 293 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/disk/DiskCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: DiskCache.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2015年12月11日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | package com.robin.lazy.cache.disk; 12 | 13 | 14 | import java.io.File; 15 | import java.io.IOException; 16 | 17 | import com.robin.lazy.cache.disk.read.ReadFromDisk; 18 | import com.robin.lazy.cache.disk.write.WriteInDisk; 19 | 20 | /** 21 | * 磁盘缓存接口 22 | * 23 | * @author jiangyufeng 24 | * @version [版本号, 2015年12月11日] 25 | * @see [相关类/方法] 26 | * @since [产品/模块版本] 27 | */ 28 | public interface DiskCache { 29 | 30 | /** 31 | * 获取磁盘缓存的根目录 32 | * 33 | * @return 磁盘缓存的根目录 34 | */ 35 | File getDirectory(); 36 | 37 | /*** 38 | * 获取当前磁盘缓存大小(单位byte字节) 39 | * @return 40 | * long 41 | * @throws 42 | * @see [类、类#方法、类#成员] 43 | */ 44 | long size(); 45 | 46 | /** 47 | * 根据key获取缓存文件 48 | * 49 | * @param key 缓存数据的key 50 | * @return 缓存文件(不存在则返回null) 51 | */ 52 | File getFile(String key); 53 | 54 | /** 55 | * 查询一条缓存数据 56 | * 57 | * @param key 58 | * 缓存数据的标识 59 | * @param readFromDisk 60 | * @return V 61 | * @throws 62 | * @see [类、类#方法、类#成员] 63 | */ 64 | V get(String key, ReadFromDisk readFromDisk); 65 | 66 | /** 67 | * 保存数据到磁盘缓存中 68 | * 69 | * @param 70 | * @param key 缓存数据对应的key 71 | * @param writeIn 写数据到磁盘的工具 72 | * @param value 缓存数据 73 | * @return 是否保存成功 74 | * @throws IOException 75 | */ 76 | boolean put(String key, WriteInDisk writeIn, V value) 77 | throws IOException; 78 | 79 | /** 80 | * 保存数据到磁盘缓存中(带有缓存期限的) 81 | * 82 | * @param 83 | * @param key 缓存数据对应的key 84 | * @param writeIn 写数据到磁盘的工具 85 | * @param value 缓存数据 86 | * @param maxLimitTime 87 | * 缓存有效期(单位秒) 88 | * @return 是否保存成功 89 | * @throws IOException 90 | */ 91 | boolean put(String key, WriteInDisk writeIn, V value, 92 | long maxLimitTime) throws IOException; 93 | 94 | /** 95 | * 根据key删除缓存文件 96 | * 97 | * @param key 缓存数据对应的key 98 | * @return 是否删除成功 99 | */ 100 | boolean remove(String key); 101 | 102 | /** 关闭缓存(执行此方法后就不能再进行缓存读写操作). */ 103 | void close(); 104 | 105 | /** 清理掉所有缓存数据. */ 106 | void clear(); 107 | } 108 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/disk/impl/BaseDiskCache.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2011-2014 Sergey Tarasevich 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *******************************************************************************/ 16 | package com.robin.lazy.cache.disk.impl; 17 | 18 | import com.robin.lazy.cache.disk.DiskCache; 19 | import com.robin.lazy.cache.disk.naming.FileNameGenerator; 20 | import com.robin.lazy.cache.disk.read.ReadFromDisk; 21 | import com.robin.lazy.cache.disk.write.WriteInDisk; 22 | import com.robin.lazy.cache.util.log.CacheLog; 23 | 24 | import java.io.File; 25 | import java.io.FileOutputStream; 26 | import java.io.IOException; 27 | 28 | /** 29 | * Base disk cache. 30 | * 31 | * @author Sergey Tarasevich 32 | * @see FileNameGenerator 33 | * @since 1.0.0 34 | */ 35 | public class BaseDiskCache implements DiskCache { 36 | private final static String LOG_TAG=BaseDiskCache.class.getSimpleName(); 37 | 38 | private static final String ERROR_ARG_NULL = " argument must be not null"; 39 | private static final String TEMP_key_POSTFIX = ".tmp"; 40 | 41 | protected final File cacheDir; 42 | protected final File reserveCacheDir; 43 | 44 | protected final FileNameGenerator fileNameGenerator; 45 | 46 | /** 47 | * @param cacheDir 48 | * Directory for file caching 49 | * @param reserveCacheDir 50 | * null-ok; Reserve directory for file caching. It's used when 51 | * the primary directory isn't available. 52 | * @param fileNameGenerator 53 | * Name generator} for cached files 54 | */ 55 | public BaseDiskCache(File cacheDir, File reserveCacheDir, 56 | FileNameGenerator fileNameGenerator) { 57 | if (cacheDir == null) { 58 | throw new IllegalArgumentException("cacheDir" + ERROR_ARG_NULL); 59 | } 60 | if (fileNameGenerator == null) { 61 | throw new IllegalArgumentException("fileNameGenerator" 62 | + ERROR_ARG_NULL); 63 | } 64 | 65 | this.cacheDir = cacheDir; 66 | this.reserveCacheDir = reserveCacheDir; 67 | this.fileNameGenerator = fileNameGenerator; 68 | } 69 | 70 | @Override 71 | public long size() { 72 | return getDirSize(getDirectory()); 73 | } 74 | 75 | /** 76 | * 获取Dir大小 77 | * @param file 78 | * @return 79 | * long 80 | * @throws 81 | * @see [类、类#方法、类#成员] 82 | */ 83 | private long getDirSize(File file) { 84 | //判断文件是否存在 85 | if (file.exists()) { 86 | //如果是目录则递归计算其内容的总大小 87 | if (file.isDirectory()) { 88 | File[] children = file.listFiles(); 89 | long size = 0; 90 | for (File f : children) 91 | size += getDirSize(f); 92 | return size; 93 | } else {//如果是文件则直接返回其大小,以byte为单位 94 | long size = file.length(); 95 | return size; 96 | } 97 | } else { 98 | CacheLog.e(LOG_TAG,"文件或者文件夹不存在,请检查路径是否正确!"); 99 | return 0; 100 | } 101 | } 102 | 103 | @Override 104 | public File getDirectory() { 105 | return cacheDir; 106 | } 107 | 108 | @Override 109 | public File getFile(String key) { 110 | String fileName = fileNameGenerator.generate(key); 111 | File dir = cacheDir; 112 | if (!cacheDir.exists() && !cacheDir.mkdirs()) { 113 | if (reserveCacheDir != null 114 | && (reserveCacheDir.exists() || reserveCacheDir.mkdirs())) { 115 | dir = reserveCacheDir; 116 | } 117 | } 118 | return new File(dir, fileName); 119 | } 120 | 121 | @Override 122 | public V get(String key, ReadFromDisk readFromDisk) { 123 | File file = getFile(key); 124 | if (file == null || !file.exists()) { 125 | return null; 126 | } 127 | return readFromDisk.readOut(file); 128 | } 129 | 130 | @Override 131 | public boolean put(String key, WriteInDisk writeIn, V value) 132 | throws IOException { 133 | boolean savedSuccessfully = false; 134 | File keyFile = getFile(key); 135 | File tmpFile = new File(keyFile.getAbsolutePath() + TEMP_key_POSTFIX); 136 | if (writeIn != null) { 137 | savedSuccessfully = writeIn.writeIn(new FileOutputStream(tmpFile), 138 | value); 139 | } 140 | if (savedSuccessfully && !tmpFile.renameTo(keyFile)) { 141 | savedSuccessfully = false; 142 | } 143 | if (!savedSuccessfully) { 144 | tmpFile.delete(); 145 | } 146 | return savedSuccessfully; 147 | } 148 | 149 | @Override 150 | public boolean put(String key, WriteInDisk writeIn, V value, 151 | long maxLimitTime) throws IOException { 152 | return put(key, writeIn, value); 153 | } 154 | 155 | @Override 156 | public boolean remove(String key) { 157 | return getFile(key).delete(); 158 | } 159 | 160 | @Override 161 | public void close() { 162 | // Nothing to do 163 | } 164 | 165 | @Override 166 | public void clear() { 167 | File[] files = cacheDir.listFiles(); 168 | if (files != null) { 169 | for (File f : files) { 170 | f.delete(); 171 | } 172 | } 173 | } 174 | 175 | } -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/disk/impl/LimitedAgeDiskCache.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2011-2014 Sergey Tarasevich 3 | *

4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | *

8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | *

10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *******************************************************************************/ 16 | package com.robin.lazy.cache.disk.impl; 17 | 18 | import com.robin.lazy.cache.LimitedAge; 19 | import com.robin.lazy.cache.disk.DiskCache; 20 | import com.robin.lazy.cache.disk.read.ReadFromDisk; 21 | import com.robin.lazy.cache.disk.write.WriteInDisk; 22 | 23 | import java.io.File; 24 | import java.io.IOException; 25 | import java.util.Collections; 26 | import java.util.HashMap; 27 | import java.util.Map; 28 | 29 | /** 30 | * 文件有过期时间的磁盘缓存实现 31 | * 32 | * @author jiangyufeng 33 | * @version [版本号, 2015年12月11日] 34 | * @see [相关类/方法] 35 | * @since [产品/模块版本] 36 | */ 37 | public class LimitedAgeDiskCache implements DiskCache { 38 | /** 39 | * 时间期限配置文件操作类 40 | */ 41 | private LimitedAgePropertiesConfig limitedAgePropertiesConfig; 42 | private DiskCache mDiskCache; 43 | private final Map loadingDates = Collections 44 | .synchronizedMap(new HashMap()); 45 | 46 | /**最大有效时间(单位秒,小于等于0时代表长期有效)*/ 47 | private long maxAge; 48 | 49 | /** 50 | * @param diskCache 磁盘缓存类 51 | * @param maxAge 缓存数据最大期限(单位秒) 52 | */ 53 | public LimitedAgeDiskCache(DiskCache diskCache, long maxAge) { 54 | this.mDiskCache = diskCache; 55 | this.maxAge = maxAge; 56 | limitedAgePropertiesConfig = new LimitedAgePropertiesConfig(getDirectory()); 57 | } 58 | 59 | @Override 60 | public File getDirectory() { 61 | if (mDiskCache == null) { 62 | return null; 63 | } 64 | return mDiskCache.getDirectory(); 65 | } 66 | 67 | @Override 68 | public File getFile(String key) { 69 | if (mDiskCache == null) { 70 | return null; 71 | } 72 | File file = mDiskCache.getFile(key); 73 | if (file != null && file.exists()) { 74 | boolean cached; 75 | LimitedAge loadingDate = loadingDates.get(file); 76 | if (loadingDate == null) { 77 | cached = false; 78 | long savaMaxAge = limitedAgePropertiesConfig.getLong(key, 0); 79 | if (savaMaxAge <= 0) { 80 | savaMaxAge = maxAge; 81 | } 82 | loadingDate = new LimitedAge(file.lastModified(), savaMaxAge); 83 | } else { 84 | cached = true; 85 | } 86 | 87 | if (loadingDate.checkExpire()) { 88 | loadingDates.remove(file); 89 | limitedAgePropertiesConfig.remove(key); 90 | mDiskCache.remove(key); 91 | file.delete(); 92 | } else if (!cached) { 93 | loadingDates.put(file, loadingDate); 94 | } 95 | } 96 | return file; 97 | } 98 | 99 | @Override 100 | public V get(String key, ReadFromDisk readFromDisk) { 101 | if (mDiskCache == null) { 102 | return null; 103 | } 104 | File file = getFile(key); 105 | if (file == null || !file.exists()) { 106 | return null; 107 | } 108 | return mDiskCache.get(key, readFromDisk); 109 | } 110 | 111 | @Override 112 | public boolean put(String key, WriteInDisk writeIn, V value) 113 | throws IOException { 114 | if (mDiskCache == null) { 115 | return false; 116 | } 117 | boolean saved = mDiskCache.put(key, writeIn, value); 118 | if (loadingDates.get(key) == null) { 119 | rememberUsage(key, maxAge); 120 | } 121 | return saved; 122 | } 123 | 124 | @Override 125 | public boolean put(String key, WriteInDisk writeIn, V value, 126 | long maxLimitTime) throws IOException { 127 | if (mDiskCache == null) { 128 | return false; 129 | } 130 | boolean saved = mDiskCache.put(key, writeIn, value, maxLimitTime); 131 | rememberUsage(key, maxLimitTime); 132 | return saved; 133 | } 134 | 135 | @Override 136 | public long size() { 137 | if (mDiskCache == null) { 138 | return 0; 139 | } 140 | return mDiskCache.size(); 141 | } 142 | 143 | @Override 144 | public boolean remove(String key) { 145 | if (mDiskCache == null) { 146 | return false; 147 | } 148 | loadingDates.remove(getFile(key)); 149 | limitedAgePropertiesConfig.remove(key); 150 | return mDiskCache.remove(key); 151 | } 152 | 153 | @Override 154 | public void clear() { 155 | if (mDiskCache != null) { 156 | mDiskCache.clear(); 157 | } 158 | if (loadingDates != null) { 159 | loadingDates.clear(); 160 | } 161 | if (limitedAgePropertiesConfig != null) { 162 | limitedAgePropertiesConfig.clear(); 163 | } 164 | } 165 | 166 | @Override 167 | public void close() { 168 | if (mDiskCache != null) { 169 | mDiskCache.close(); 170 | mDiskCache = null; 171 | } 172 | if (loadingDates != null) { 173 | loadingDates.clear(); 174 | } 175 | limitedAgePropertiesConfig = null; 176 | } 177 | 178 | /** 179 | * 记录数据有效时间 180 | * 181 | * @param key 182 | * @param mMaxlimitTime void 183 | * @throws 184 | * @see [类、类#方法、类#成员] 185 | */ 186 | private void rememberUsage(String key, long mMaxlimitTime) { 187 | File file = getFile(key); 188 | long currentTime = System.currentTimeMillis(); 189 | file.setLastModified(currentTime); 190 | limitedAgePropertiesConfig.setLong(key, mMaxlimitTime); 191 | loadingDates.put(file, new LimitedAge(currentTime, mMaxlimitTime)); 192 | } 193 | 194 | /** 195 | * 获取数据剩余有效时间(单位秒,-1为始终有效) 196 | * 197 | * @return long 198 | * @throws 199 | * @see [类、类#方法、类#成员] 200 | */ 201 | public long getLimitedTime(String key) { 202 | File file = getFile(key); 203 | if (loadingDates != null && loadingDates.containsKey(file)) { 204 | LimitedAge limitedAge = loadingDates.get(file); 205 | if (limitedAge != null) { 206 | return limitedAge.limitedTime(); 207 | } 208 | } 209 | return -1; 210 | } 211 | 212 | } -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/disk/impl/LimitedAgePropertiesConfig.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 文 件 名: LimitedAgePropertiesConfig.java 3 | * 版 权: Technologies Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: 江钰锋 00501 6 | * 修改时间: 16/8/9 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache.disk.impl; 13 | 14 | import java.io.File; 15 | import java.io.FileInputStream; 16 | import java.io.FileOutputStream; 17 | import java.io.IOException; 18 | import java.io.InputStream; 19 | import java.io.OutputStream; 20 | import java.util.Properties; 21 | 22 | /** 23 | * 时间缓存期限配置文件 24 | * 25 | * @author 江钰锋 00501 26 | * @version [版本号, 16/8/9] 27 | * @see [相关类/方法] 28 | * @since [产品/模块版本] 29 | */ 30 | public class LimitedAgePropertiesConfig { 31 | private Properties mProperties; 32 | private File file; 33 | 34 | public LimitedAgePropertiesConfig(File fileDirectory) { 35 | file = new File(fileDirectory, "limitedage.properties"); 36 | } 37 | 38 | /** 39 | * 设置long类型配置 40 | * 41 | * @param key 42 | * @param value 43 | */ 44 | public void setLong(String key, long value) { 45 | if (value > 0) { 46 | setString(key, String.valueOf(value)); 47 | } 48 | } 49 | 50 | /** 51 | * 获取long类型配置数据 52 | * 53 | * @param key 54 | * @param defaultVales 55 | * @return 56 | */ 57 | public long getLong(String key, long defaultVales) { 58 | try { 59 | return Long.parseLong(getString(key, String.valueOf(defaultVales))); 60 | } catch (NumberFormatException e) { 61 | e.printStackTrace(); 62 | } 63 | return defaultVales; 64 | } 65 | 66 | /** 67 | * 设置sting类型配置 68 | * 69 | * @param key 70 | * @param value 71 | */ 72 | public void setString(String key, String value) { 73 | if (value != null) { 74 | Properties props = getProperties(); 75 | props.setProperty(key, value); 76 | setProperties(props); 77 | } 78 | } 79 | 80 | /*** 81 | * 获取对应的配置 82 | * 83 | * @param key 84 | * @param defaultValue 85 | * @return 86 | */ 87 | public String getString(String key, String defaultValue) { 88 | return getProperties().getProperty(key, defaultValue); 89 | } 90 | 91 | /** 92 | * 删除对应的配置 93 | * 94 | * @param key 95 | */ 96 | public void remove(String key) { 97 | Properties props = getProperties(); 98 | props.remove(key); 99 | setProperties(props); 100 | } 101 | 102 | /** 103 | * 返回配置关于配置实体 104 | * 105 | * @return 返回配置实体 106 | */ 107 | private Properties getProperties() { 108 | if (mProperties == null) { 109 | mProperties = new Properties(); 110 | InputStream in = null; 111 | try { 112 | in = new FileInputStream(file); 113 | mProperties.load(in); 114 | in.close(); 115 | } catch (IOException e) { 116 | e.printStackTrace(); 117 | } catch (Exception e) { 118 | e.printStackTrace(); 119 | } finally { 120 | try { 121 | if (in != null) { 122 | in.close(); 123 | } 124 | } catch (IOException e) { 125 | e.printStackTrace(); 126 | } 127 | } 128 | } 129 | return mProperties; 130 | } 131 | 132 | /** 133 | * 设置配置的内容 134 | * 135 | * @param properties 136 | */ 137 | private void setProperties(Properties properties) { 138 | if (properties == null) return; 139 | OutputStream out = null; 140 | try { 141 | out = new FileOutputStream(file); 142 | properties.store(out, null); 143 | out.flush(); 144 | } catch (IOException e) { 145 | e.printStackTrace(); 146 | } catch (Exception e) { 147 | e.printStackTrace(); 148 | } finally { 149 | try { 150 | if (out != null) { 151 | out.close(); 152 | } 153 | } catch (IOException e) { 154 | e.printStackTrace(); 155 | } 156 | } 157 | } 158 | 159 | /** 160 | * 清理 161 | */ 162 | public void clear() { 163 | Properties props = getProperties(); 164 | props.clear(); 165 | setProperties(props); 166 | } 167 | 168 | } 169 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/disk/impl/ext/LruDiskCache.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2014 Sergey Tarasevich 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *******************************************************************************/ 16 | package com.robin.lazy.cache.disk.impl.ext; 17 | 18 | import com.robin.lazy.cache.disk.DiskCache; 19 | import com.robin.lazy.cache.disk.naming.FileNameGenerator; 20 | import com.robin.lazy.cache.disk.read.ReadFromDisk; 21 | import com.robin.lazy.cache.disk.write.WriteInDisk; 22 | import com.robin.lazy.cache.util.log.CacheLog; 23 | 24 | import java.io.File; 25 | import java.io.IOException; 26 | 27 | /** 28 | * Lru算法的磁盘缓存实现 29 | * 30 | * @author jiangyufeng 31 | * @version [版本号, 2015年12月11日] 32 | * @see [相关类/方法] 33 | * @since [产品/模块版本] 34 | */ 35 | public class LruDiskCache implements DiskCache { 36 | 37 | private final static String LOG_TAG=LruDiskCache.class.getSimpleName(); 38 | 39 | private static final String ERROR_ARG_NULL = " argument must be not null"; 40 | private static final String ERROR_ARG_NEGATIVE = " argument must be positive number"; 41 | 42 | protected DiskLruCache cache; 43 | private File reserveCacheDir; 44 | 45 | protected final FileNameGenerator fileNameGenerator; 46 | 47 | /** 48 | * @param cacheDir 49 | * Directory for file caching 50 | * @param fileNameGenerator 51 | * Name generator} for cached files. Generated names must match 52 | * the regex [a-z0-9_-]{1,64} 53 | * @param cacheMaxSize 54 | * Max cache size in bytes. 0 means cache size is 55 | * unlimited. 56 | * @throws IOException 57 | * if cache can't be initialized (e.g. 58 | * "No space left on device") 59 | */ 60 | public LruDiskCache(File cacheDir, FileNameGenerator fileNameGenerator, 61 | long cacheMaxSize) throws IOException { 62 | this(cacheDir, null, fileNameGenerator, cacheMaxSize, 0); 63 | } 64 | 65 | /** 66 | * @param cacheDir 67 | * Directory for file caching 68 | * @param reserveCacheDir 69 | * null-ok; Reserve directory for file caching. It's used when 70 | * the primary directory isn't available. 71 | * @param fileNameGenerator 72 | * Name generator} for cached files. Generated names must match 73 | * the regex [a-z0-9_-]{1,64} 74 | * @param cacheMaxSize 75 | * Max cache size in bytes. 0 means cache size is 76 | * unlimited. 77 | * @param cacheMaxFileCount 78 | * Max file count in cache. 0 means file count is 79 | * unlimited. 80 | * @throws IOException 81 | * if cache can't be initialized (e.g. 82 | * "No space left on device") 83 | */ 84 | public LruDiskCache(File cacheDir, File reserveCacheDir, 85 | FileNameGenerator fileNameGenerator, long cacheMaxSize, 86 | int cacheMaxFileCount) throws IOException { 87 | if (cacheDir == null) { 88 | throw new IllegalArgumentException("cacheDir" + ERROR_ARG_NULL); 89 | } 90 | if (cacheMaxSize < 0) { 91 | throw new IllegalArgumentException("cacheMaxSize" 92 | + ERROR_ARG_NEGATIVE); 93 | } 94 | if (cacheMaxFileCount < 0) { 95 | throw new IllegalArgumentException("cacheMaxFileCount" 96 | + ERROR_ARG_NEGATIVE); 97 | } 98 | if (fileNameGenerator == null) { 99 | throw new IllegalArgumentException("fileNameGenerator" 100 | + ERROR_ARG_NULL); 101 | } 102 | 103 | if (cacheMaxSize == 0) { 104 | cacheMaxSize = Long.MAX_VALUE; 105 | } 106 | if (cacheMaxFileCount == 0) { 107 | cacheMaxFileCount = Integer.MAX_VALUE; 108 | } 109 | 110 | this.reserveCacheDir = reserveCacheDir; 111 | this.fileNameGenerator = fileNameGenerator; 112 | initCache(cacheDir, reserveCacheDir, cacheMaxSize, cacheMaxFileCount); 113 | } 114 | 115 | private void initCache(File cacheDir, File reserveCacheDir, 116 | long cacheMaxSize, int cacheMaxFileCount) throws IOException { 117 | try { 118 | cache = DiskLruCache.open(cacheDir, 1, 1, cacheMaxSize, 119 | cacheMaxFileCount); 120 | } catch (IOException e) { 121 | CacheLog.e(LOG_TAG,e.getMessage(),e); 122 | if (reserveCacheDir != null) { 123 | initCache(reserveCacheDir, null, cacheMaxSize, 124 | cacheMaxFileCount); 125 | } 126 | if (cache == null) { 127 | throw e; // new RuntimeException("Can't initialize disk cache", 128 | // e); 129 | } 130 | } 131 | } 132 | 133 | @Override 134 | public long size() { 135 | return cache.size(); 136 | } 137 | 138 | @Override 139 | public File getDirectory() { 140 | return cache.getDirectory(); 141 | } 142 | 143 | @Override 144 | public File getFile(String key) { 145 | DiskLruCache.Snapshot snapshot = null; 146 | try { 147 | snapshot = cache.get(getKey(key)); 148 | return snapshot == null ? null : snapshot.getFile(0); 149 | } catch (IOException e) { 150 | CacheLog.e(LOG_TAG,e.getMessage(), e); 151 | return null; 152 | } finally { 153 | if (snapshot != null) { 154 | snapshot.close(); 155 | } 156 | } 157 | } 158 | @Override 159 | public V get(String key, ReadFromDisk readFromDisk) { 160 | File file = getFile(key); 161 | if (file == null || !file.exists()) { 162 | return null; 163 | } 164 | return readFromDisk.readOut(file); 165 | } 166 | 167 | @Override 168 | public boolean put(String key, WriteInDisk writeIn, V value) 169 | throws IOException { 170 | 171 | DiskLruCache.Editor editor = cache.edit(getKey(key)); 172 | if (editor == null) { 173 | return false; 174 | } 175 | boolean savedSuccessfully = false; 176 | if (writeIn != null) { 177 | savedSuccessfully = writeIn.writeIn(editor.newOutputStream(0), 178 | value); 179 | } 180 | if (savedSuccessfully) { 181 | editor.commit(); 182 | } else { 183 | editor.abort(); 184 | } 185 | return savedSuccessfully; 186 | } 187 | 188 | @Override 189 | public boolean put(String key, WriteInDisk writeIn, V value, 190 | long maxLimitTime) throws IOException { 191 | return put(key, writeIn, value); 192 | } 193 | 194 | @Override 195 | public boolean remove(String key) { 196 | try { 197 | return cache.remove(getKey(key)); 198 | } catch (IOException e) { 199 | CacheLog.e(LOG_TAG,e.getMessage(), e); 200 | return false; 201 | } 202 | } 203 | 204 | @Override 205 | public void close() { 206 | try { 207 | cache.close(); 208 | } catch (IOException e) { 209 | CacheLog.e(LOG_TAG,e.getMessage(), e); 210 | } 211 | cache = null; 212 | } 213 | 214 | @Override 215 | public void clear() { 216 | try { 217 | cache.delete(); 218 | } catch (IOException e) { 219 | CacheLog.e(LOG_TAG,e.getMessage(), e); 220 | } 221 | try { 222 | initCache(cache.getDirectory(), reserveCacheDir, 223 | cache.getMaxSize(), cache.getMaxFileCount()); 224 | } catch (IOException e) { 225 | CacheLog.e(LOG_TAG,e.getMessage(), e); 226 | } 227 | } 228 | 229 | private String getKey(String key) { 230 | return fileNameGenerator.generate(key); 231 | } 232 | 233 | } 234 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/disk/impl/ext/StrictLineReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.robin.lazy.cache.disk.impl.ext; 17 | 18 | import java.io.ByteArrayOutputStream; 19 | import java.io.Closeable; 20 | import java.io.EOFException; 21 | import java.io.IOException; 22 | import java.io.InputStream; 23 | import java.io.UnsupportedEncodingException; 24 | import java.nio.charset.Charset; 25 | 26 | /** 27 | * Buffers input from an {@link InputStream} for reading lines. 28 | * 29 | *

This class is used for buffered reading of lines. For purposes of this class, a line ends 30 | * with "\n" or "\r\n". End of input is reported by throwing {@code EOFException}. Unterminated 31 | * line at end of input is invalid and will be ignored, the caller may use {@code 32 | * hasUnterminatedLine()} to detect it after catching the {@code EOFException}. 33 | * 34 | *

This class is intended for reading input that strictly consists of lines, such as line-based 35 | * cache entries or cache journal. Unlike the {@link java.io.BufferedReader} which in conjunction 36 | * with {@link java.io.InputStreamReader} provides similar functionality, this class uses different 37 | * end-of-input reporting and a more restrictive definition of a line. 38 | * 39 | *

This class supports only charsets that encode '\r' and '\n' as a single byte with value 13 40 | * and 10, respectively, and the representation of no other character contains these values. 41 | * We currently check in constructor that the charset is one of US-ASCII, UTF-8 and ISO-8859-1. 42 | * The default charset is US_ASCII. 43 | */ 44 | class StrictLineReader implements Closeable { 45 | private static final byte CR = (byte) '\r'; 46 | private static final byte LF = (byte) '\n'; 47 | 48 | private final InputStream in; 49 | private final Charset charset; 50 | 51 | /* 52 | * Buffered data is stored in {@code buf}. As long as no exception occurs, 0 <= pos <= end 53 | * and the data in the range [pos, end) is buffered for reading. At end of input, if there is 54 | * an unterminated line, we set end == -1, otherwise end == pos. If the underlying 55 | * {@code InputStream} throws an {@code IOException}, end may remain as either pos or -1. 56 | */ 57 | private byte[] buf; 58 | private int pos; 59 | private int end; 60 | 61 | /** 62 | * Constructs a new {@code LineReader} with the specified charset and the default capacity. 63 | * 64 | * @param in the {@code InputStream} to read data from. 65 | * @param charset the charset used to decode data. Only US-ASCII, UTF-8 and ISO-8859-1 are 66 | * supported. 67 | * @throws NullPointerException if {@code in} or {@code charset} is null. 68 | * @throws IllegalArgumentException if the specified charset is not supported. 69 | */ 70 | public StrictLineReader(InputStream in, Charset charset) { 71 | this(in, 8192, charset); 72 | } 73 | 74 | /** 75 | * Constructs a new {@code LineReader} with the specified capacity and charset. 76 | * 77 | * @param in the {@code InputStream} to read data from. 78 | * @param capacity the capacity of the buffer. 79 | * @param charset the charset used to decode data. Only US-ASCII, UTF-8 and ISO-8859-1 are 80 | * supported. 81 | * @throws NullPointerException if {@code in} or {@code charset} is null. 82 | * @throws IllegalArgumentException if {@code capacity} is negative or zero 83 | * or the specified charset is not supported. 84 | */ 85 | public StrictLineReader(InputStream in, int capacity, Charset charset) { 86 | if (in == null || charset == null) { 87 | throw new NullPointerException(); 88 | } 89 | if (capacity < 0) { 90 | throw new IllegalArgumentException("capacity <= 0"); 91 | } 92 | if (!(charset.equals(Util.US_ASCII))) { 93 | throw new IllegalArgumentException("Unsupported encoding"); 94 | } 95 | 96 | this.in = in; 97 | this.charset = charset; 98 | buf = new byte[capacity]; 99 | } 100 | 101 | /** 102 | * Closes the reader by closing the underlying {@code InputStream} and 103 | * marking this reader as closed. 104 | * 105 | * @throws IOException for errors when closing the underlying {@code InputStream}. 106 | */ 107 | public void close() throws IOException { 108 | synchronized (in) { 109 | if (buf != null) { 110 | buf = null; 111 | in.close(); 112 | } 113 | } 114 | } 115 | 116 | /** 117 | * Reads the next line. A line ends with {@code "\n"} or {@code "\r\n"}, 118 | * this end of line marker is not included in the result. 119 | * 120 | * @return the next line from the input. 121 | * @throws IOException for underlying {@code InputStream} errors. 122 | * @throws EOFException for the end of source stream. 123 | */ 124 | public String readLine() throws IOException { 125 | synchronized (in) { 126 | if (buf == null) { 127 | throw new IOException("LineReader is closed"); 128 | } 129 | 130 | // Read more data if we are at the end of the buffered data. 131 | // Though it's an error to read after an exception, we will let {@code fillBuf()} 132 | // throw again if that happens; thus we need to handle end == -1 as well as end == pos. 133 | if (pos >= end) { 134 | fillBuf(); 135 | } 136 | // Try to find LF in the buffered data and return the line if successful. 137 | for (int i = pos; i != end; ++i) { 138 | if (buf[i] == LF) { 139 | int lineEnd = (i != pos && buf[i - 1] == CR) ? i - 1 : i; 140 | String res = new String(buf, pos, lineEnd - pos, charset.name()); 141 | pos = i + 1; 142 | return res; 143 | } 144 | } 145 | 146 | // Let's anticipate up to 80 characters on top of those already read. 147 | ByteArrayOutputStream out = new ByteArrayOutputStream(end - pos + 80) { 148 | @Override 149 | public String toString() { 150 | int length = (count > 0 && buf[count - 1] == CR) ? count - 1 : count; 151 | try { 152 | return new String(buf, 0, length, charset.name()); 153 | } catch (UnsupportedEncodingException e) { 154 | throw new AssertionError(e); // Since we control the charset this will never happen. 155 | } 156 | } 157 | }; 158 | 159 | while (true) { 160 | out.write(buf, pos, end - pos); 161 | // Mark unterminated line in case fillBuf throws EOFException or IOException. 162 | end = -1; 163 | fillBuf(); 164 | // Try to find LF in the buffered data and return the line if successful. 165 | for (int i = pos; i != end; ++i) { 166 | if (buf[i] == LF) { 167 | if (i != pos) { 168 | out.write(buf, pos, i - pos); 169 | } 170 | pos = i + 1; 171 | return out.toString(); 172 | } 173 | } 174 | } 175 | } 176 | } 177 | 178 | /** 179 | * Reads new input data into the buffer. Call only with pos == end or end == -1, 180 | * depending on the desired outcome if the function throws. 181 | */ 182 | private void fillBuf() throws IOException { 183 | int result = in.read(buf, 0, buf.length); 184 | if (result == -1) { 185 | throw new EOFException(); 186 | } 187 | pos = 0; 188 | end = result; 189 | } 190 | } 191 | 192 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/disk/impl/ext/Util.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.robin.lazy.cache.disk.impl.ext; 17 | 18 | import java.io.Closeable; 19 | import java.io.File; 20 | import java.io.IOException; 21 | import java.io.Reader; 22 | import java.io.StringWriter; 23 | import java.nio.charset.Charset; 24 | 25 | /** Junk drawer of utility methods. */ 26 | final class Util { 27 | static final Charset US_ASCII = Charset.forName("US-ASCII"); 28 | static final Charset UTF_8 = Charset.forName("UTF-8"); 29 | 30 | private Util() { 31 | } 32 | 33 | static String readFully(Reader reader) throws IOException { 34 | try { 35 | StringWriter writer = new StringWriter(); 36 | char[] buffer = new char[1024]; 37 | int count; 38 | while ((count = reader.read(buffer)) != -1) { 39 | writer.write(buffer, 0, count); 40 | } 41 | return writer.toString(); 42 | } finally { 43 | reader.close(); 44 | } 45 | } 46 | 47 | /** 48 | * Deletes the contents of {@code dir}. Throws an IOException if any file 49 | * could not be deleted, or if {@code dir} is not a readable directory. 50 | */ 51 | static void deleteContents(File dir) throws IOException { 52 | File[] files = dir.listFiles(); 53 | if (files == null) { 54 | throw new IOException("not a readable directory: " + dir); 55 | } 56 | for (File file : files) { 57 | if (file.isDirectory()) { 58 | deleteContents(file); 59 | } 60 | if (!file.delete()) { 61 | throw new IOException("failed to delete file: " + file); 62 | } 63 | } 64 | } 65 | 66 | static void closeQuietly(/*Auto*/Closeable closeable) { 67 | if (closeable != null) { 68 | try { 69 | closeable.close(); 70 | } catch (RuntimeException rethrown) { 71 | throw rethrown; 72 | } catch (Exception ignored) { 73 | } 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/disk/naming/FileNameGenerator.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2011-2013 Sergey Tarasevich 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *******************************************************************************/ 16 | package com.robin.lazy.cache.disk.naming; 17 | 18 | /** 19 | * 名称转换器 20 | * 21 | * @author jiangyufeng 22 | * @version [版本号, 2015年12月15日] 23 | * @see [相关类/方法] 24 | * @since [产品/模块版本] 25 | */ 26 | public interface FileNameGenerator { 27 | 28 | /** 29 | * 转换名称 30 | * @param keyName 31 | * @return 32 | */ 33 | String generate(String keyName); 34 | } 35 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/disk/naming/HashCodeFileNameGenerator.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2011-2013 Sergey Tarasevich 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *******************************************************************************/ 16 | package com.robin.lazy.cache.disk.naming; 17 | 18 | /** 19 | * Names image file as image URI {@linkplain String#hashCode() hashcode} 20 | * 21 | * @author 22 | * @since 23 | */ 24 | public class HashCodeFileNameGenerator implements FileNameGenerator { 25 | @Override 26 | public String generate(String imageUri) { 27 | return String.valueOf(imageUri.hashCode()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/disk/naming/Md5FileNameGenerator.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2011-2013 Sergey Tarasevich 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *******************************************************************************/ 16 | package com.robin.lazy.cache.disk.naming; 17 | 18 | import com.robin.lazy.cache.util.log.CacheLog; 19 | 20 | import java.math.BigInteger; 21 | import java.security.MessageDigest; 22 | import java.security.NoSuchAlgorithmException; 23 | 24 | /** 25 | * Names image file as MD5 hash of image URI 26 | * 27 | * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) 28 | * @since 1.4.0 29 | */ 30 | public class Md5FileNameGenerator implements FileNameGenerator { 31 | 32 | private final static String LOG_TAG=Md5FileNameGenerator.class.getSimpleName(); 33 | 34 | private static final String HASH_ALGORITHM = "MD5"; 35 | private static final int RADIX = 10 + 26; // 10 digits + 26 letters 36 | 37 | @Override 38 | public String generate(String imageUri) { 39 | byte[] md5 = getMD5(imageUri.getBytes()); 40 | BigInteger bi = new BigInteger(md5).abs(); 41 | return bi.toString(RADIX); 42 | } 43 | 44 | private byte[] getMD5(byte[] data) { 45 | byte[] hash = null; 46 | try { 47 | MessageDigest digest = MessageDigest.getInstance(HASH_ALGORITHM); 48 | digest.update(data); 49 | hash = digest.digest(); 50 | } catch (NoSuchAlgorithmException e) { 51 | CacheLog.e(LOG_TAG, e.getMessage(),e); 52 | } 53 | return hash; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/disk/read/BitmapReadFromDisk.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: BitmapReadFromDisk.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2015年12月11日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache.disk.read; 13 | 14 | import android.graphics.Bitmap; 15 | import android.graphics.BitmapFactory; 16 | import android.graphics.BitmapFactory.Options; 17 | import android.graphics.Matrix; 18 | import android.media.ExifInterface; 19 | 20 | import com.robin.lazy.cache.util.log.CacheLog; 21 | import com.robin.lazy.util.IoUtils; 22 | import com.robin.lazy.util.bitmap.ImageDecodingInfo; 23 | import com.robin.lazy.util.bitmap.ImageScaleType; 24 | import com.robin.lazy.util.bitmap.ImageSize; 25 | import com.robin.lazy.util.bitmap.ImageSizeUtils; 26 | 27 | import java.io.File; 28 | import java.io.FileInputStream; 29 | import java.io.IOException; 30 | import java.io.InputStream; 31 | 32 | /** 33 | * 从文件中读取图片 34 | * 35 | * @author jiangyufeng 36 | * @version [版本号, 2015年12月11日] 37 | * @see [相关类/方法] 38 | * @since [产品/模块版本] 39 | */ 40 | public class BitmapReadFromDisk implements ReadFromDisk { 41 | 42 | private final static String LOG_TAG=BitmapReadFromDisk.class.getSimpleName(); 43 | 44 | private ImageDecodingInfo imDecodeInfor; 45 | 46 | public BitmapReadFromDisk(ImageDecodingInfo imDecodeInfor) { 47 | this.imDecodeInfor = imDecodeInfor; 48 | } 49 | 50 | @Override 51 | public Bitmap readOut(File file) { 52 | Bitmap decodedBitmap = null; 53 | ImageFileInfo imageInfo = null; 54 | InputStream imageStream = null; 55 | try { 56 | imageStream = getImageStream(file); 57 | imageInfo = defineImageSizeAndRotation(file.getAbsolutePath(), 58 | imageStream, imDecodeInfor); 59 | imageStream = resetStream(file, imageStream, imDecodeInfor); 60 | Options decodingOptions = prepareDecodingOptions( 61 | imageInfo.imageSize, imDecodeInfor); 62 | decodedBitmap = BitmapFactory.decodeStream(imageStream, null, 63 | decodingOptions); 64 | } catch (IOException e) { 65 | } finally { 66 | IoUtils.closeSilently(imageStream); 67 | } 68 | if (decodedBitmap == null || imageInfo == null) { 69 | CacheLog.e(LOG_TAG,"Image can't be decoded [%s]"); 70 | } else { 71 | decodedBitmap = considerExactScaleAndOrientatiton(decodedBitmap, 72 | imDecodeInfor, imageInfo.exif.rotation, 73 | imageInfo.exif.flipHorizontal); 74 | } 75 | return decodedBitmap; 76 | } 77 | 78 | /*** 79 | * 获取文件流 80 | * 81 | * @param file 82 | * @return 83 | * @throws IOException 84 | * InputStream 85 | * @throws 86 | * @see [类、类#方法、类#成员] 87 | */ 88 | private InputStream getImageStream(File file) throws IOException { 89 | return new FileInputStream(file); 90 | } 91 | 92 | protected Options prepareDecodingOptions(ImageSize imageSize, 93 | ImageDecodingInfo decodingInfo) { 94 | ImageScaleType scaleType = decodingInfo.getImageScaleType(); 95 | int scale; 96 | if (scaleType == ImageScaleType.NONE) { 97 | scale = 1; 98 | } else if (scaleType == ImageScaleType.NONE_SAFE) { 99 | scale = ImageSizeUtils.computeMinImageSampleSize(imageSize); 100 | } else { 101 | ImageSize targetSize = decodingInfo.getTargetSize(); 102 | boolean powerOf2 = scaleType == ImageScaleType.IN_SAMPLE_POWER_OF_2; 103 | scale = ImageSizeUtils.computeImageSampleSize(imageSize, 104 | targetSize, decodingInfo.getViewScaleType(), powerOf2); 105 | } 106 | Options decodingOptions = decodingInfo.getDecodingOptions(); 107 | decodingOptions.inSampleSize = scale; 108 | return decodingOptions; 109 | } 110 | 111 | private InputStream resetStream(File fileName, InputStream imageStream, 112 | ImageDecodingInfo decodingInfo) throws IOException { 113 | try { 114 | imageStream.reset(); 115 | } catch (IOException e) { 116 | IoUtils.closeSilently(imageStream); 117 | imageStream = getImageStream(fileName); 118 | } 119 | return imageStream; 120 | } 121 | 122 | private boolean canDefineExifParams(String mimeType) { 123 | return "image/jpeg".equalsIgnoreCase(mimeType); 124 | } 125 | 126 | private ExifInfo defineExifOrientation(String filePath) { 127 | int rotation = 0; 128 | boolean flip = false; 129 | try { 130 | ExifInterface exif = new ExifInterface(filePath); 131 | int exifOrientation = exif.getAttributeInt( 132 | ExifInterface.TAG_ORIENTATION, 133 | ExifInterface.ORIENTATION_NORMAL); 134 | switch (exifOrientation) { 135 | case ExifInterface.ORIENTATION_FLIP_HORIZONTAL : 136 | flip = true; 137 | case ExifInterface.ORIENTATION_NORMAL : 138 | rotation = 0; 139 | break; 140 | case ExifInterface.ORIENTATION_TRANSVERSE : 141 | flip = true; 142 | case ExifInterface.ORIENTATION_ROTATE_90 : 143 | rotation = 90; 144 | break; 145 | case ExifInterface.ORIENTATION_FLIP_VERTICAL : 146 | flip = true; 147 | case ExifInterface.ORIENTATION_ROTATE_180 : 148 | rotation = 180; 149 | break; 150 | case ExifInterface.ORIENTATION_TRANSPOSE : 151 | flip = true; 152 | case ExifInterface.ORIENTATION_ROTATE_270 : 153 | rotation = 270; 154 | break; 155 | } 156 | } catch (IOException e) { 157 | CacheLog.e("e", "Can't read EXIF tags from file [%s] \n"+filePath); 158 | } 159 | return new ExifInfo(rotation, flip); 160 | } 161 | 162 | private ImageFileInfo defineImageSizeAndRotation(String filePath, 163 | InputStream imageStream, ImageDecodingInfo decodingInfo) 164 | throws IOException { 165 | Options options = new Options(); 166 | options.inJustDecodeBounds = true; 167 | BitmapFactory.decodeStream(imageStream, null, options); 168 | 169 | ExifInfo exif; 170 | if (decodingInfo.shouldConsiderExifParams() 171 | && canDefineExifParams(options.outMimeType)) { 172 | exif = defineExifOrientation(filePath); 173 | } else { 174 | exif = new ExifInfo(); 175 | } 176 | return new ImageFileInfo(new ImageSize(options.outWidth, 177 | options.outHeight, exif.rotation), exif); 178 | } 179 | 180 | private Bitmap considerExactScaleAndOrientatiton(Bitmap subsampledBitmap, 181 | ImageDecodingInfo decodingInfo, int rotation, boolean flipHorizontal) { 182 | Matrix m = new Matrix(); 183 | // Scale to exact size if need 184 | ImageScaleType scaleType = decodingInfo.getImageScaleType(); 185 | if (scaleType == ImageScaleType.EXACTLY 186 | || scaleType == ImageScaleType.EXACTLY_STRETCHED) { 187 | ImageSize srcSize = new ImageSize(subsampledBitmap.getWidth(), 188 | subsampledBitmap.getHeight(), rotation); 189 | float scale = ImageSizeUtils.computeImageScale(srcSize, 190 | decodingInfo.getTargetSize(), 191 | decodingInfo.getViewScaleType(), 192 | scaleType == ImageScaleType.EXACTLY_STRETCHED); 193 | if (Float.compare(scale, 1f) != 0) { 194 | m.setScale(scale, scale); 195 | } 196 | } 197 | // Flip bitmap if need 198 | if (flipHorizontal) { 199 | m.postScale(-1, 1); 200 | } 201 | // Rotate bitmap if need 202 | if (rotation != 0) { 203 | m.postRotate(rotation); 204 | } 205 | 206 | Bitmap finalBitmap = Bitmap.createBitmap(subsampledBitmap, 0, 0, 207 | subsampledBitmap.getWidth(), subsampledBitmap.getHeight(), m, 208 | true); 209 | if (finalBitmap != subsampledBitmap) { 210 | subsampledBitmap.recycle(); 211 | } 212 | return finalBitmap; 213 | } 214 | 215 | private static class ExifInfo { 216 | 217 | public final int rotation; 218 | public final boolean flipHorizontal; 219 | 220 | private ExifInfo() { 221 | this.rotation = 0; 222 | this.flipHorizontal = false; 223 | } 224 | 225 | private ExifInfo(int rotation, boolean flipHorizontal) { 226 | this.rotation = rotation; 227 | this.flipHorizontal = flipHorizontal; 228 | } 229 | } 230 | 231 | private static class ImageFileInfo { 232 | 233 | public final ImageSize imageSize; 234 | public final ExifInfo exif; 235 | 236 | private ImageFileInfo(ImageSize imageSize, ExifInfo exif) { 237 | this.imageSize = imageSize; 238 | this.exif = exif; 239 | } 240 | } 241 | } 242 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/disk/read/BytesReadFromDisk.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: BytesReadFromDisk.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2015年12月16日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache.disk.read; 13 | 14 | import com.robin.lazy.cache.util.log.CacheLog; 15 | import com.robin.lazy.util.IoUtils; 16 | 17 | import java.io.ByteArrayOutputStream; 18 | import java.io.File; 19 | import java.io.FileInputStream; 20 | import java.io.FileNotFoundException; 21 | import java.io.IOException; 22 | import java.io.InputStream; 23 | 24 | /** 25 | * 从文件中读取byte数组 26 | * 27 | * @author jiangyufeng 28 | * @version [版本号, 2015年12月16日] 29 | * @see [相关类/方法] 30 | * @since [产品/模块版本] 31 | */ 32 | public class BytesReadFromDisk implements ReadFromDisk { 33 | 34 | private final static String LOG_TAG=BytesReadFromDisk.class.getSimpleName(); 35 | 36 | private static final int DEFAULT_BUFFER_SIZE = 1 * 1024; // 4 Kb 37 | 38 | /** 缓冲流大小 */ 39 | private int bufferSize = DEFAULT_BUFFER_SIZE; 40 | 41 | @Override 42 | public byte[] readOut(File file) { 43 | byte[] bytes = null; 44 | InputStream input = null; 45 | ByteArrayOutputStream baos = null; 46 | try { 47 | byte[] tmp = new byte[bufferSize]; 48 | input = new FileInputStream(file); 49 | baos = new ByteArrayOutputStream(); 50 | int size = 0; 51 | while ((size = input.read(tmp)) != -1) { 52 | baos.write(tmp, 0, size); 53 | } 54 | bytes = baos.toByteArray(); 55 | } catch (FileNotFoundException e) { 56 | CacheLog.e(LOG_TAG,"从文件读取byte字节数组失败,没有找到文件",e); 57 | } catch (IOException e) { 58 | CacheLog.e(LOG_TAG, "从文件读取byte字节数组失败",e); 59 | } catch (Exception e) { 60 | CacheLog.e(LOG_TAG, "从文件读取byte字节数组失败",e); 61 | } finally { 62 | IoUtils.closeSilently(input); 63 | IoUtils.closeSilently(baos); 64 | } 65 | return bytes; 66 | } 67 | 68 | /** 69 | * 设置缓冲流大小 70 | * 71 | * @param bufferSize 72 | * void 73 | * @throws 74 | * @see [类、类#方法、类#成员] 75 | */ 76 | public void setBufferSize(int bufferSize) { 77 | this.bufferSize = bufferSize; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/disk/read/InputStreamReadFormDisk.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: InputStreamReadFormDisk.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2015年12月11日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache.disk.read; 13 | 14 | import com.robin.lazy.cache.util.log.CacheLog; 15 | 16 | import java.io.File; 17 | import java.io.FileInputStream; 18 | import java.io.FileNotFoundException; 19 | import java.io.InputStream; 20 | 21 | /** 22 | * 读取文件流 23 | * 24 | * @author jiangyufeng 25 | * @version [版本号, 2015年12月11日] 26 | * @see [相关类/方法] 27 | * @since [产品/模块版本] 28 | */ 29 | public class InputStreamReadFormDisk implements ReadFromDisk { 30 | 31 | private final static String LOG_TAG=InputStreamReadFormDisk.class.getSimpleName(); 32 | 33 | @Override 34 | public InputStream readOut(File file) { 35 | InputStream input = null; 36 | try { 37 | input = new FileInputStream(file); 38 | } catch (FileNotFoundException e) { 39 | CacheLog.e(LOG_TAG, "读取InputStream错误",e); 40 | } catch (Exception e) { 41 | CacheLog.e(LOG_TAG, "读取InputStream错误",e); 42 | } 43 | return input; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/disk/read/ReadFromDisk.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: DiskFileDecode.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2015年12月11日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache.disk.read; 13 | 14 | import java.io.File; 15 | 16 | /** 17 | * 读取磁盘缓存方法接口 18 | * 19 | * @author jiangyufeng 20 | * @version [版本号, 2015年12月11日] 21 | * @param 22 | * @see [相关类/方法] 23 | * @since [产品/模块版本] 24 | */ 25 | public interface ReadFromDisk { 26 | 27 | /*** 28 | * 读文文件中内容 29 | * @param file 30 | * @return 31 | * V 32 | * @throws 33 | * @see [类、类#方法、类#成员] 34 | */ 35 | V readOut(File file); 36 | } 37 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/disk/read/SerializableReadFromDisk.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: SerialzableReadFromDisk.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2015年12月11日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache.disk.read; 13 | 14 | import com.robin.lazy.cache.CacheLoaderManager; 15 | import com.robin.lazy.cache.util.log.CacheLog; 16 | import com.robin.lazy.util.IoUtils; 17 | 18 | import java.io.File; 19 | import java.io.FileInputStream; 20 | import java.io.IOException; 21 | import java.io.ObjectInputStream; 22 | import java.io.Serializable; 23 | import java.io.StreamCorruptedException; 24 | 25 | /** 26 | * 从文件中读取对象 27 | * 28 | * @author jiangyufeng 29 | * @version [版本号, 2015年12月11日] 30 | * @see [相关类/方法] 31 | * @since [产品/模块版本] 32 | */ 33 | public class SerializableReadFromDisk implements ReadFromDisk { 34 | 35 | private final static String LOG_TAG=SerializableReadFromDisk.class.getSimpleName(); 36 | 37 | @SuppressWarnings("unchecked") 38 | @Override 39 | public V readOut(File file) { 40 | V result = null; 41 | ObjectInputStream read = null; 42 | try { 43 | read = new ObjectInputStream(new FileInputStream(file)); 44 | result=(V)read.readObject(); 45 | } catch (StreamCorruptedException e) { 46 | CacheLog.e(LOG_TAG,"读取Serialzable错误",e); 47 | } catch (IOException e) { 48 | CacheLog.e(LOG_TAG,"读取Serialzable错误",e); 49 | } catch (ClassNotFoundException e) { 50 | CacheLog.e(LOG_TAG, "读取Serialzable错误",e); 51 | }finally{ 52 | IoUtils.closeSilently(read); 53 | } 54 | return result; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/disk/read/StringReadFromDisk.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: StringDiskFileDecode.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2015年12月11日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache.disk.read; 13 | 14 | import android.util.Log; 15 | 16 | import com.robin.lazy.cache.util.log.CacheLog; 17 | import com.robin.lazy.util.IoUtils; 18 | 19 | import java.io.BufferedReader; 20 | import java.io.File; 21 | import java.io.FileInputStream; 22 | import java.io.IOException; 23 | import java.io.InputStreamReader; 24 | import java.io.StreamCorruptedException; 25 | 26 | /** 27 | * 把本地文件解码成String 28 | * 29 | * @author jiangyufeng 30 | * @version [版本号, 2015年12月11日] 31 | * @see [相关类/方法] 32 | * @since [产品/模块版本] 33 | */ 34 | public class StringReadFromDisk implements ReadFromDisk { 35 | private final static String LOG_TAG=StringReadFromDisk.class.getSimpleName(); 36 | 37 | private final String DEFAULT_CHARSET = "UTF-8"; 38 | 39 | /** 40 | * 编码类型 41 | */ 42 | private String responseCharset = DEFAULT_CHARSET; 43 | 44 | @Override 45 | public String readOut(File File) { 46 | String s = null; 47 | BufferedReader read = null; 48 | try { 49 | // 创建字符流缓冲区 50 | read = new BufferedReader(new InputStreamReader( 51 | new FileInputStream(File), responseCharset));// 缓冲 52 | StringBuffer stBuffer = new StringBuffer(); 53 | String temp = null; 54 | while ((temp = read.readLine()) != null) { 55 | stBuffer.append(temp); 56 | } 57 | s = stBuffer.toString(); 58 | } catch (StreamCorruptedException e) { 59 | CacheLog.e(LOG_TAG, "读取String错误",e); 60 | } catch (IOException e) { 61 | CacheLog.e(LOG_TAG, "读取String错误",e); 62 | } finally { 63 | IoUtils.closeSilently(read); 64 | } 65 | return s; 66 | } 67 | /*** 68 | * 设置String的编码类型 69 | * 70 | * @param responseCharset 71 | * void 72 | * @throws 73 | * @see [类、类#方法、类#成员] 74 | */ 75 | public void setResponseCharset(String responseCharset) { 76 | this.responseCharset = responseCharset; 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/disk/write/BitmapWriteInDisk.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: BitmapWriteInCache.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2015年12月9日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache.disk.write; 13 | 14 | import android.graphics.Bitmap; 15 | 16 | import com.robin.lazy.cache.util.log.CacheLog; 17 | import com.robin.lazy.util.IoUtils; 18 | 19 | import java.io.BufferedOutputStream; 20 | import java.io.OutputStream; 21 | 22 | /** 23 | * 把图片写入缓存 24 | * 25 | * @author jiangyufeng 26 | * @version [版本号, 2015年12月9日] 27 | * @see [相关类/方法] 28 | * @since [产品/模块版本] 29 | */ 30 | public class BitmapWriteInDisk extends WriteInDisk { 31 | 32 | private final static String LOG_TAG=BitmapWriteInDisk.class.getSimpleName(); 33 | 34 | private static final int DEFAULT_BUFFER_SIZE = 32 * 1024; // 32 Kb 35 | 36 | private static final Bitmap.CompressFormat DEFAULT_COMPRESS_FORMAT = Bitmap.CompressFormat.PNG; 37 | 38 | private static final int DEFAULT_COMPRESS_QUALITY = 100; 39 | 40 | /** 图片格式 */ 41 | private Bitmap.CompressFormat compressFormat = DEFAULT_COMPRESS_FORMAT; 42 | 43 | /** 缓冲流大小 */ 44 | private int bufferSize = DEFAULT_BUFFER_SIZE; 45 | 46 | /** 压缩质量 */ 47 | private int compressQuality = DEFAULT_COMPRESS_QUALITY; 48 | 49 | /** 是否回收 */ 50 | private boolean isRecycle; 51 | 52 | public BitmapWriteInDisk(boolean isRecycle) { 53 | this.isRecycle = isRecycle; 54 | } 55 | 56 | @Override 57 | public boolean writeIn(OutputStream out,Bitmap values) { 58 | OutputStream os = new BufferedOutputStream(out, bufferSize); 59 | boolean isSuccess = false; 60 | try { 61 | isSuccess = values.compress(compressFormat, compressQuality, 62 | os); 63 | os.flush(); 64 | } catch (Exception e) { 65 | CacheLog.e(LOG_TAG,"Bitmap写入缓存错误",e); 66 | } finally { 67 | IoUtils.closeSilently(os); 68 | if (isRecycle) { 69 | values.recycle(); 70 | } 71 | } 72 | return isSuccess; 73 | } 74 | 75 | /** 76 | * 设置图片格式 77 | * 78 | * @param compressFormat 79 | * 格式 void 80 | * @throws 81 | * @see [类、类#方法、类#成员] 82 | */ 83 | public void setCompressFormat(Bitmap.CompressFormat compressFormat) { 84 | this.compressFormat = compressFormat; 85 | } 86 | 87 | /** 88 | * 设置缓冲流大小 89 | * 90 | * @param bufferSize 91 | * void 92 | * @throws 93 | * @see [类、类#方法、类#成员] 94 | */ 95 | public void setBufferSize(int bufferSize) { 96 | this.bufferSize = bufferSize; 97 | } 98 | 99 | /*** 100 | * 设置图片质量 101 | * 102 | * @param compressQuality 103 | * void 104 | * @throws 105 | * @see [类、类#方法、类#成员] 106 | */ 107 | public void setCompressQuality(int compressQuality) { 108 | this.compressQuality = compressQuality; 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/disk/write/BytesWriteInDisk.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: BytesWriteInDisk.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2015年12月16日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache.disk.write; 13 | 14 | 15 | import com.robin.lazy.cache.util.log.CacheLog; 16 | import com.robin.lazy.util.IoUtils; 17 | 18 | import java.io.IOException; 19 | import java.io.OutputStream; 20 | 21 | /** 22 | * byte数组写入文件 23 | * 24 | * @author jiangyufeng 25 | * @version [版本号, 2015年12月16日] 26 | * @see [相关类/方法] 27 | * @since [产品/模块版本] 28 | */ 29 | public class BytesWriteInDisk extends WriteInDisk { 30 | 31 | private final static String LOG_TAG=BytesWriteInDisk.class.getSimpleName(); 32 | 33 | @Override 34 | public boolean writeIn(OutputStream out,byte[] values) { 35 | boolean isSucess = false; 36 | try { 37 | out.write(values); 38 | out.flush(); 39 | } catch (IOException e) { 40 | CacheLog.e(LOG_TAG,"byte数组写入文件错误",e); 41 | } catch (Exception e) { 42 | CacheLog.e(LOG_TAG, "byte数组写入文件错误",e); 43 | } 44 | IoUtils.closeSilently(out); 45 | return isSucess; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/disk/write/InputStreamWriteInDisk.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: InputStreamWriteInCache.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2015年12月9日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache.disk.write; 13 | 14 | 15 | import com.robin.lazy.cache.util.log.CacheLog; 16 | import com.robin.lazy.util.IoUtils; 17 | 18 | import java.io.IOException; 19 | import java.io.InputStream; 20 | import java.io.OutputStream; 21 | 22 | /** 23 | * InputStream写入缓存 24 | * 25 | * @author jiangyufeng 26 | * @version [版本号, 2015年12月9日] 27 | * @see [相关类/方法] 28 | * @since [产品/模块版本] 29 | */ 30 | public class InputStreamWriteInDisk extends WriteInDisk { 31 | 32 | private final static String LOG_TAG=InputStreamWriteInDisk.class.getSimpleName(); 33 | 34 | private static final int DEFAULT_BUFFER_SIZE = 4 * 1024; // 4 Kb 35 | 36 | /** 缓冲流大小 */ 37 | private int bufferSize = DEFAULT_BUFFER_SIZE; 38 | 39 | private IoUtils.CopyListener mListener; 40 | 41 | public InputStreamWriteInDisk(IoUtils.CopyListener listener) { 42 | this.mListener = listener; 43 | } 44 | 45 | @Override 46 | public boolean writeIn(OutputStream out,InputStream values) { 47 | boolean isSucess = false; 48 | try { 49 | isSucess = IoUtils.copyStream(values, out, mListener, 50 | bufferSize); 51 | out.flush(); 52 | } catch (IOException e) { 53 | CacheLog.e(LOG_TAG, "InputStream写入缓存错误",e); 54 | } catch (Exception e) { 55 | CacheLog.e(LOG_TAG, "InputStream写入缓存错误",e); 56 | } finally { 57 | IoUtils.closeSilently(out); 58 | } 59 | return isSucess; 60 | 61 | } 62 | 63 | /** 64 | * 设置缓冲流大小 65 | * 66 | * @param bufferSize 67 | * void 68 | * @throws 69 | * @see [类、类#方法、类#成员] 70 | */ 71 | public void setBufferSize(int bufferSize) { 72 | this.bufferSize = bufferSize; 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/disk/write/SerializableWriteInDisk.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: StrigWriteInCache.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2015年12月9日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache.disk.write; 13 | 14 | 15 | import com.robin.lazy.cache.disk.read.InputStreamReadFormDisk; 16 | import com.robin.lazy.cache.util.log.CacheLog; 17 | import com.robin.lazy.util.IoUtils; 18 | 19 | import java.io.IOException; 20 | import java.io.ObjectOutputStream; 21 | import java.io.OutputStream; 22 | import java.io.Serializable; 23 | 24 | /** 25 | * 把string 写入OutputStream中 26 | * 27 | * @author jiangyufeng 28 | * @version [版本号, 2015年12月9日] 29 | * @see [相关类/方法] 30 | * @since [产品/模块版本] 31 | */ 32 | public class SerializableWriteInDisk extends WriteInDisk { 33 | 34 | private final static String LOG_TAG=SerializableWriteInDisk.class.getSimpleName(); 35 | 36 | @Override 37 | public boolean writeIn(OutputStream out,V values){ 38 | ObjectOutputStream objectOut = null; 39 | boolean isSucce = false; 40 | try { 41 | objectOut = new ObjectOutputStream(out); 42 | objectOut.writeObject(values); 43 | objectOut.flush(); 44 | isSucce=true; 45 | } catch (IOException e) { 46 | CacheLog.e(LOG_TAG, "Serialzable写入缓存错误",e); 47 | }catch (Exception e) { 48 | CacheLog.e(LOG_TAG, "Serialzable写入缓存错误",e); 49 | }finally{ 50 | IoUtils.closeSilently(objectOut); 51 | } 52 | return isSucce; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/disk/write/StringWriteInDisk.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: StrigWriteInCache.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2015年12月9日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache.disk.write; 13 | 14 | 15 | import com.robin.lazy.cache.util.log.CacheLog; 16 | import com.robin.lazy.util.IoUtils; 17 | 18 | import java.io.IOException; 19 | import java.io.OutputStream; 20 | import java.io.OutputStreamWriter; 21 | import java.io.Writer; 22 | 23 | /** 24 | * 把string 写入OutputStream中 25 | * 26 | * @author jiangyufeng 27 | * @version [版本号, 2015年12月9日] 28 | * @see [相关类/方法] 29 | * @since [产品/模块版本] 30 | */ 31 | public class StringWriteInDisk extends WriteInDisk { 32 | 33 | private final static String LOG_TAG=StringWriteInDisk.class.getSimpleName(); 34 | 35 | private final String DEFAULT_CHARSET = "UTF-8"; 36 | 37 | /** 38 | * 编码类型 39 | */ 40 | private String responseCharset = DEFAULT_CHARSET; 41 | 42 | @Override 43 | public boolean writeIn(OutputStream out,String values) { 44 | Writer writer = null; 45 | boolean isSucce = false; 46 | try { 47 | writer = new OutputStreamWriter(out, responseCharset); 48 | writer.write(values); 49 | writer.flush(); 50 | isSucce = true; 51 | } catch (IOException e) { 52 | CacheLog.e(LOG_TAG, "String写入缓存错误",e); 53 | } catch (Exception e) { 54 | CacheLog.e(LOG_TAG, "String写入缓存错误",e); 55 | }finally { 56 | IoUtils.closeSilently(writer); 57 | } 58 | return isSucce; 59 | } 60 | 61 | /*** 62 | * 设置String的编码类型 63 | * @param responseCharset 64 | * void 65 | * @throws 66 | * @see [类、类#方法、类#成员] 67 | */ 68 | public void setResponseCharset(String responseCharset) { 69 | this.responseCharset = responseCharset; 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/disk/write/WriteInDisk.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: WriteInCacheBase.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2015年12月9日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache.disk.write; 13 | 14 | import java.io.OutputStream; 15 | 16 | /** 17 | * 数据写入磁盘缓存方法类 18 | * 19 | * @author jiangyufeng 20 | * @version [版本号, 2015年12月9日] 21 | * @param 22 | * @see [相关类/方法] 23 | * @since [产品/模块版本] 24 | */ 25 | public abstract class WriteInDisk { 26 | 27 | /*** 28 | * 把数据写入OutputStream中 29 | * @param value 要存入磁盘中的值 30 | * @param out 31 | * @return boolean 32 | * @throws 33 | * @see [类、类#方法、类#成员] 34 | */ 35 | public abstract boolean writeIn(OutputStream out,V value); 36 | } 37 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/entity/CacheGetEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: CacheGetEntity.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2015年12月16日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache.entity; 13 | 14 | import com.robin.lazy.cache.disk.read.ReadFromDisk; 15 | 16 | /** 17 | * 缓存请求参数实体 18 | * 19 | * @author jiangyufeng 20 | * @version [版本号, 2015年12月16日] 21 | * @param 22 | * @see [相关类/方法] 23 | * @since [产品/模块版本] 24 | */ 25 | public class CacheGetEntity { 26 | /*** 27 | * 磁盘缓存读取 28 | */ 29 | private ReadFromDisk readFromDisk; 30 | 31 | /** 32 | * <默认构造函数> 33 | */ 34 | public CacheGetEntity(ReadFromDisk readFromDisk) { 35 | this.readFromDisk = readFromDisk; 36 | } 37 | 38 | public ReadFromDisk getReadFromDisk() { 39 | return readFromDisk; 40 | } 41 | 42 | public void setReadFromDisk(ReadFromDisk readFromDisk) { 43 | this.readFromDisk = readFromDisk; 44 | } 45 | 46 | 47 | } 48 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/entity/CachePutEntity.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: InsertCacheEntity.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2015年12月14日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache.entity; 13 | 14 | import com.robin.lazy.cache.disk.write.WriteInDisk; 15 | 16 | /** 17 | * 缓存存储参数实体 18 | * 19 | * @author jiangyufeng 20 | * @version [版本号, 2015年12月14日] 21 | * @param 22 | * @see [相关类/方法] 23 | * @since [产品/模块版本] 24 | */ 25 | public class CachePutEntity { 26 | 27 | private WriteInDisk writeInDisk; 28 | 29 | public CachePutEntity(WriteInDisk writeInDisk) { 30 | this.writeInDisk = writeInDisk; 31 | } 32 | 33 | /** 34 | * 获取磁盘缓存写入方式接口 35 | * @return 36 | * WriteInDisk 37 | * @throws 38 | * @see [类、类#方法、类#成员] 39 | */ 40 | public WriteInDisk getWriteInDisk() { 41 | return writeInDisk; 42 | } 43 | 44 | /*** 45 | * 设置磁盘缓存写入方式接口 46 | * @param writeInDisk 47 | * void 48 | * @throws 49 | * @see [类、类#方法、类#成员] 50 | */ 51 | public void setWriteInDisk(WriteInDisk writeInDisk) { 52 | this.writeInDisk = writeInDisk; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/memory/EntryRemovedProcess.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: EntryRemovedProcess.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2016年1月13日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache.memory; 13 | /** 14 | * 数据被删除后进行垃圾回收的一些处理 15 | * 16 | * @author jiangyufeng 17 | * @version [版本号, 2016年1月13日] 18 | * @param 19 | * @see [相关类/方法] 20 | * @since [产品/模块版本] 21 | */ 22 | public class EntryRemovedProcess { 23 | 24 | /*** 25 | * 当item被回收或者删掉时调用。改方法当value被回收释放存储空间时被remove调用, 26 | * 或者替换item值时put调用,默认实现什么都没做。 27 | * 28 | * @param evicted 是否释放被删除的空间 29 | * @param key 30 | * @param oldValue 老的数据 31 | * @param newValue 新数据 void 32 | * @throws 33 | * @see [类、类#方法、类#成员] 34 | */ 35 | public void entryRemoved(boolean evicted, String key, V oldValue, 36 | V newValue) { 37 | oldValue = null; 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/memory/MemoryCache.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2014 Sergey Tarasevich 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *******************************************************************************/ 16 | package com.robin.lazy.cache.memory; 17 | 18 | import com.robin.lazy.cache.Cache; 19 | 20 | import java.util.Collection; 21 | import java.util.Map; 22 | 23 | /** 24 | * 内存缓存操作接口 25 | * 26 | * @author jiangyufeng 27 | * @version [版本号, 2015年12月15日] 28 | * @see [相关类/方法] 29 | * @since [产品/模块版本] 30 | */ 31 | public interface MemoryCache extends Cache { 32 | 33 | /** 34 | * 获取所有的key 35 | * @return 36 | */ 37 | Collection keys(); 38 | 39 | /** 40 | * 获取缓存数据集合 41 | * @return 42 | */ 43 | Map snapshot(); 44 | 45 | } 46 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/memory/SizeOfCacheCalculator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: SizeOfCacheCalculator.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2015年12月17日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache.memory; 13 | 14 | import android.graphics.Bitmap; 15 | 16 | /** 17 | * 内存大小计算器 18 | * 19 | * @author jiangyufeng 20 | * @version [版本号, 2015年12月17日] 21 | * @param 22 | * @see [相关类/方法] 23 | * @since [产品/模块版本] 24 | */ 25 | public class SizeOfCacheCalculator { 26 | 27 | /** 28 | * 计算一个缓存数据的大小,默认是1(就是一个数据) 29 | * 30 | * @param key 31 | * @param value 32 | * @return int 33 | * @throws 34 | * @see [类、类#方法、类#成员] 35 | */ 36 | public int sizeOf(String key, V value) { 37 | if (value instanceof Bitmap) { 38 | Bitmap bitmap = (Bitmap) value; 39 | return bitmap.getRowBytes() * bitmap.getHeight(); 40 | } else if (value instanceof byte[]) { 41 | return ((byte[]) value).length; 42 | } 43 | return 1; 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/memory/impl/EntryRemovedProcessMemoryCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: EntryRemovedProcessMemoryCache.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2016年1月13日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache.memory.impl; 13 | 14 | import com.robin.lazy.cache.memory.EntryRemovedProcess; 15 | 16 | /** 17 | *可以自定义数据被删除后的垃圾回收处理的缓存 18 | * 19 | * @author jiangyufeng 20 | * @version [版本号, 2016年1月13日] 21 | * @see [相关类/方法] 22 | * @since [产品/模块版本] 23 | */ 24 | public class EntryRemovedProcessMemoryCache extends LruMemoryCache { 25 | 26 | /** 27 | * 垃圾回收处理者 28 | */ 29 | @SuppressWarnings("rawtypes") 30 | private EntryRemovedProcess mEntryRemovedProcess; 31 | 32 | public EntryRemovedProcessMemoryCache(int maxSize, 33 | EntryRemovedProcess entryRemovedProcess) { 34 | super(maxSize); 35 | this.mEntryRemovedProcess = entryRemovedProcess; 36 | } 37 | 38 | @SuppressWarnings("unchecked") 39 | @Override 40 | protected void entryRemoved(boolean evicted, String key, V oldValue, 41 | V newValue) { 42 | if (mEntryRemovedProcess != null) { 43 | mEntryRemovedProcess.entryRemoved(evicted, key, oldValue, newValue); 44 | } else { 45 | super.entryRemoved(evicted, key, oldValue, newValue); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/memory/impl/FuzzyKeyMemoryCache.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2011-2014 Sergey Tarasevich 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *******************************************************************************/ 16 | package com.robin.lazy.cache.memory.impl; 17 | 18 | 19 | import com.robin.lazy.cache.memory.MemoryCache; 20 | import com.robin.lazy.cache.util.log.CacheLog; 21 | 22 | import java.util.Collection; 23 | import java.util.Comparator; 24 | import java.util.Map; 25 | 26 | /** 27 | * Decorator for {@link MemoryCache}. Provides special feature for cache: some 28 | * different keys are considered as equals (using {@link Comparator comparator} 29 | * ). And when you try to put some value into cache by key so entries with 30 | * "equals" keys will be removed from cache before.
31 | * NOTE: Used for internal needs. Normally you don't need to use this 32 | * class. 33 | * 34 | * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) 35 | * @since 1.0.0 36 | */ 37 | public class FuzzyKeyMemoryCache implements MemoryCache { 38 | 39 | private final static String LOG_TAG=FuzzyKeyMemoryCache.class.getSimpleName(); 40 | 41 | private final MemoryCache cache; 42 | private final Comparator keyComparator; 43 | 44 | public FuzzyKeyMemoryCache(MemoryCache cache, 45 | Comparator keyComparator) { 46 | this.cache = cache; 47 | this.keyComparator = keyComparator; 48 | } 49 | 50 | @Override 51 | public boolean put(String key, V value) { 52 | if (cache == null) { 53 | CacheLog.e(LOG_TAG, "MemoryCache缓存操作对象为空",new NullPointerException()); 54 | return false; 55 | } 56 | // Search equal key and remove this entry 57 | synchronized (cache) { 58 | String keyToRemove = null; 59 | for (String cacheKey : cache.keys()) { 60 | if (keyComparator.compare(key, cacheKey) == 0) { 61 | keyToRemove = cacheKey; 62 | break; 63 | } 64 | } 65 | if (keyToRemove != null) { 66 | cache.remove(keyToRemove); 67 | } 68 | } 69 | return cache.put(key, value); 70 | } 71 | 72 | @Override 73 | public boolean put(String key, V value, long maxLimitTime) { 74 | if (cache == null) { 75 | CacheLog.e(LOG_TAG, "MemoryCache缓存操作对象为空",new NullPointerException()); 76 | return false; 77 | } 78 | synchronized (cache) { 79 | String keyToRemove = null; 80 | for (String cacheKey : cache.keys()) { 81 | if (keyComparator.compare(key, cacheKey) == 0) { 82 | keyToRemove = cacheKey; 83 | break; 84 | } 85 | } 86 | if (keyToRemove != null) { 87 | cache.remove(keyToRemove); 88 | } 89 | } 90 | return cache.put(key, value, maxLimitTime); 91 | } 92 | 93 | @Override 94 | public V get(String key) { 95 | if (cache == null) { 96 | CacheLog.e(LOG_TAG, "MemoryCache缓存操作对象为空",new NullPointerException()); 97 | return null; 98 | } 99 | return cache.get(key); 100 | } 101 | 102 | @Override 103 | public boolean remove(String key) { 104 | if (cache == null) { 105 | CacheLog.e(LOG_TAG ,"MemoryCache缓存操作对象为空",new NullPointerException()); 106 | return false; 107 | } 108 | return cache.remove(key); 109 | } 110 | 111 | @Override 112 | public Collection keys() { 113 | if (cache == null) { 114 | CacheLog.e(LOG_TAG, "MemoryCache缓存操作对象为空",new NullPointerException()); 115 | return null; 116 | } 117 | return cache.keys(); 118 | } 119 | 120 | @Override 121 | public Map snapshot() { 122 | if (cache == null) { 123 | CacheLog.e(LOG_TAG, "MemoryCache缓存操作对象为空",new NullPointerException()); 124 | return null; 125 | } 126 | return cache.snapshot(); 127 | } 128 | 129 | @Override 130 | public void resize(int maxSize) { 131 | if (cache == null) { 132 | CacheLog.e(LOG_TAG, "MemoryCache缓存操作对象为空",new NullPointerException()); 133 | return; 134 | } 135 | cache.resize(maxSize); 136 | } 137 | 138 | @Override 139 | public void clear() { 140 | if (cache == null) { 141 | CacheLog.e(LOG_TAG, "MemoryCache缓存操作对象为空",new NullPointerException()); 142 | return; 143 | } 144 | cache.clear(); 145 | } 146 | 147 | @Override 148 | public void close() { 149 | if (cache == null) { 150 | CacheLog.e(LOG_TAG, "MemoryCache缓存操作对象为空",new NullPointerException()); 151 | return; 152 | } 153 | cache.close(); 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/memory/impl/LimitedAgeMemoryCache.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2011-2014 Sergey Tarasevich 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *******************************************************************************/ 16 | package com.robin.lazy.cache.memory.impl; 17 | 18 | import android.icu.util.TimeUnit; 19 | import android.util.TimeUtils; 20 | 21 | import com.robin.lazy.cache.LimitedAge; 22 | import com.robin.lazy.cache.memory.MemoryCache; 23 | import com.robin.lazy.cache.util.log.CacheLog; 24 | 25 | import java.sql.Timestamp; 26 | import java.util.Collection; 27 | import java.util.Collections; 28 | import java.util.HashMap; 29 | import java.util.Map; 30 | 31 | /** 32 | * Decorator for {@link MemoryCache}. Provides special feature for cache: if 33 | * some cached object age exceeds defined value then this object will be removed 34 | * from cache. 35 | * 36 | * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) 37 | * @see MemoryCache 38 | * @since 1.3.1 39 | */ 40 | public class LimitedAgeMemoryCache implements MemoryCache { 41 | 42 | private final static String LOG_TAG=LimitedAgeMemoryCache.class.getSimpleName(); 43 | 44 | private final MemoryCache cache; 45 | 46 | /**缓存数据最大保存时间(单位秒,小于等于0时代表长期有效)*/ 47 | private final long maxAge; 48 | private final Map loadingDates = Collections 49 | .synchronizedMap(new HashMap()); 50 | 51 | /** 52 | * @param cache 53 | * Wrapped memory cache 54 | * @param maxAge 55 | * Max object age (in seconds). If object age will exceed 56 | * this value then it'll be removed from cache on next treatment 57 | * (and therefore be reloaded). 58 | */ 59 | public LimitedAgeMemoryCache(MemoryCache cache, long maxAge) { 60 | this.cache = cache; 61 | this.maxAge = maxAge; 62 | } 63 | 64 | @Override 65 | public boolean put(String key, V value) { 66 | if (cache == null) { 67 | CacheLog.e(LOG_TAG, "MemoryCache缓存操作对象为空",new NullPointerException()); 68 | return false; 69 | } 70 | boolean putSuccesfully = cache.put(key, value); 71 | if (putSuccesfully) { 72 | loadingDates.put(key, new LimitedAge(System.currentTimeMillis(), 73 | maxAge)); 74 | } 75 | return putSuccesfully; 76 | } 77 | 78 | @Override 79 | public boolean put(String key, V value, long maxLimitTime) { 80 | if (cache == null) { 81 | CacheLog.e(LOG_TAG, "MemoryCache缓存操作对象为空",new NullPointerException()); 82 | return false; 83 | } 84 | boolean putSuccesfully = cache.put(key, value); 85 | if (putSuccesfully) { 86 | loadingDates.put(key, new LimitedAge(System.currentTimeMillis(), 87 | maxLimitTime)); 88 | } 89 | return putSuccesfully; 90 | } 91 | 92 | @Override 93 | public V get(String key) { 94 | if (cache == null) { 95 | CacheLog.e(LOG_TAG,"MemoryCache缓存操作对象为空",new NullPointerException()); 96 | return null; 97 | } 98 | LimitedAge loadingDate = loadingDates.get(key); 99 | if (loadingDate != null && loadingDate.checkExpire()) { 100 | cache.remove(key); 101 | loadingDates.remove(key); 102 | } 103 | 104 | return cache.get(key); 105 | } 106 | 107 | @Override 108 | public boolean remove(String key) { 109 | if (cache == null) { 110 | CacheLog.e(LOG_TAG,"MemoryCache缓存操作对象为空",new NullPointerException()); 111 | return false; 112 | } 113 | loadingDates.remove(key); 114 | return cache.remove(key); 115 | } 116 | 117 | @Override 118 | public Collection keys() { 119 | if (cache == null) { 120 | CacheLog.e(LOG_TAG, "MemoryCache缓存操作对象为空",new NullPointerException()); 121 | return null; 122 | } 123 | return cache.keys(); 124 | } 125 | 126 | @Override 127 | public Map snapshot() { 128 | if (cache == null) { 129 | CacheLog.e(LOG_TAG, "MemoryCache缓存操作对象为空",new NullPointerException()); 130 | return null; 131 | } 132 | return cache.snapshot(); 133 | } 134 | 135 | @Override 136 | public void resize(int maxSize) { 137 | if (cache == null) { 138 | CacheLog.e(LOG_TAG, "MemoryCache缓存操作对象为空",new NullPointerException()); 139 | return; 140 | } 141 | cache.resize(maxSize); 142 | } 143 | 144 | @Override 145 | public void clear() { 146 | if (cache == null) { 147 | CacheLog.e(LOG_TAG, "MemoryCache缓存操作对象为空",new NullPointerException()); 148 | return; 149 | } 150 | loadingDates.clear(); 151 | cache.clear(); 152 | } 153 | 154 | @Override 155 | public void close() { 156 | if (cache == null) { 157 | CacheLog.e(LOG_TAG, "MemoryCache缓存操作对象为空",new NullPointerException()); 158 | return; 159 | } 160 | loadingDates.clear(); 161 | cache.close(); 162 | } 163 | 164 | } 165 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/memory/impl/LruMemoryCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: LruMemoryCache.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2015年12月14日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache.memory.impl; 13 | 14 | import com.robin.lazy.cache.memory.MemoryCache; 15 | import com.robin.lazy.cache.memory.impl.ext.LruCache; 16 | import com.robin.lazy.cache.util.log.CacheLog; 17 | 18 | import java.util.Collection; 19 | import java.util.HashSet; 20 | import java.util.Map; 21 | 22 | /** 23 | * Lru算法的内存缓存 24 | * 25 | * @author jiangyufeng 26 | * @version [版本号, 2015年12月14日] 27 | * @see [相关类/方法] 28 | * @since [产品/模块版本] 29 | */ 30 | public class LruMemoryCache implements MemoryCache { 31 | 32 | private final static String LOG_TAG=LruMemoryCache.class.getSimpleName(); 33 | 34 | /** 内存缓存存储类 */ 35 | private LruCache lruCache; 36 | 37 | /*** 38 | * @param maxSize 39 | * 内存最大限度 40 | */ 41 | public LruMemoryCache(int maxSize) { 42 | if (maxSize <= 0) { 43 | throw new IllegalArgumentException("maxSize <= 0"); 44 | } 45 | lruCache = new LruCache(maxSize) { 46 | @Override 47 | protected int sizeOf(String key, Object value) { 48 | return LruMemoryCache.this.sizeOf(key, value); 49 | } 50 | 51 | protected void entryRemoved(boolean evicted, String key, 52 | Object oldValue, Object newValue) { 53 | LruMemoryCache.this.entryRemoved(evicted, key, oldValue, 54 | newValue); 55 | }; 56 | }; 57 | } 58 | 59 | @Override 60 | public boolean put(String key, V value) { 61 | if (key == null || value == null) { 62 | throw new NullPointerException("key == null || value == null"); 63 | } 64 | if (lruCache != null) { 65 | try { 66 | lruCache.put(key, value); 67 | return true; 68 | } catch (NullPointerException e) { 69 | CacheLog.e(LOG_TAG, "put to menory fail",e); 70 | } catch (Exception e) { 71 | CacheLog.e(LOG_TAG, "put to menory fail",e); 72 | } 73 | } 74 | return false; 75 | } 76 | 77 | @Override 78 | public boolean put(String key, V value, long maxLimitTime) { 79 | return put(key, value); 80 | } 81 | 82 | @SuppressWarnings("unchecked") 83 | @Override 84 | public V get(String key) { 85 | if (key == null) { 86 | throw new NullPointerException("key == null"); 87 | } 88 | if (lruCache != null) { 89 | V values = null; 90 | try { 91 | values = (V) lruCache.get(key); 92 | } catch (NullPointerException e) { 93 | CacheLog.e(LOG_TAG, "缓存数据不存在,不能强制类型转换",e); 94 | } catch (ClassCastException e) { 95 | CacheLog.e(LOG_TAG, "强制类型转换错误,不符合的类型",e); 96 | } catch (Exception e) { 97 | CacheLog.e(LOG_TAG, e.getMessage(),e); 98 | } 99 | return values; 100 | } 101 | return null; 102 | } 103 | 104 | @Override 105 | public boolean remove(String key) { 106 | if (key == null) { 107 | throw new NullPointerException("key == null"); 108 | } 109 | if (lruCache != null && lruCache.remove(key) != null) { 110 | return true; 111 | } 112 | return false; 113 | } 114 | 115 | @Override 116 | public Map snapshot() { 117 | if (lruCache != null) { 118 | return lruCache.snapshot(); 119 | } 120 | return null; 121 | } 122 | 123 | @Override 124 | public Collection keys() { 125 | Map map = snapshot(); 126 | if (map != null) { 127 | return new HashSet(map.keySet()); 128 | } 129 | return null; 130 | 131 | } 132 | 133 | @Override 134 | public void resize(int maxSize) { 135 | if (maxSize <= 0) { 136 | throw new IllegalArgumentException("maxSize <= 0"); 137 | } 138 | if (lruCache != null) { 139 | lruCache.resize(maxSize); 140 | } 141 | } 142 | 143 | @Override 144 | public void clear() { 145 | if (lruCache != null) { 146 | lruCache.evictAll(); 147 | } 148 | } 149 | 150 | @Override 151 | public void close() { 152 | clear(); 153 | if (lruCache != null) { 154 | lruCache = null; 155 | } 156 | } 157 | 158 | /*** 159 | * 当item被回收或者删掉时调用。改方法当value被回收释放存储空间时被remove调用, 160 | * 或者替换item值时put调用,默认实现什么都没做。 161 | * 162 | * @param 163 | * @param evicted 是否释放被删除的空间 164 | * @param key 165 | * @param oldValue 老的数据 166 | * @param newValue 新数据 void 167 | * @throws 168 | * @see [类、类#方法、类#成员] 169 | */ 170 | protected void entryRemoved(boolean evicted, String key, V oldValue, 171 | V newValue) { 172 | oldValue = null; 173 | }; 174 | 175 | /** 176 | * 计算一个缓存数据的大小,默认是1(就是一个数据) 177 | * 178 | * @param 179 | * 180 | * @param key 181 | * @param value 182 | * @return int 183 | * @throws 184 | * @see [类、类#方法、类#成员] 185 | */ 186 | protected int sizeOf(String key, V value) { 187 | return 1; 188 | } 189 | 190 | @Override 191 | public final String toString() { 192 | if (lruCache != null) { 193 | return lruCache.toString(); 194 | } 195 | return String.format("LruCache[maxSize=%d]", 0); 196 | } 197 | 198 | } 199 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/memory/impl/SizeOfMemoryCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: SizeOfMemoryCache.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2015年12月17日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache.memory.impl; 13 | 14 | import com.robin.lazy.cache.memory.SizeOfCacheCalculator; 15 | 16 | /** 17 | * 重新计算每个缓存数据占的大小的缓存类 18 | * 19 | * @author jiangyufeng 20 | * @version [版本号, 2015年12月17日] 21 | * @see [相关类/方法] 22 | * @since [产品/模块版本] 23 | */ 24 | public class SizeOfMemoryCache extends LruMemoryCache { 25 | 26 | /** 一个缓存占用的内存计算器 */ 27 | @SuppressWarnings("rawtypes") 28 | private SizeOfCacheCalculator cacheCalculator; 29 | 30 | public SizeOfMemoryCache(int maxSize, SizeOfCacheCalculator cacheCalculator) { 31 | super(maxSize); 32 | this.cacheCalculator = cacheCalculator; 33 | } 34 | 35 | @SuppressWarnings("unchecked") 36 | @Override 37 | protected int sizeOf(String key, V value) { 38 | if (key != null && value == null) { 39 | return super.sizeOf(key, value); 40 | } else if (key == null && value == null) { 41 | return 0; 42 | } 43 | if (cacheCalculator != null) { 44 | return cacheCalculator.sizeOf(key, value); 45 | } 46 | return super.sizeOf(key, value); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/memory/impl/ext/LruCache.java: -------------------------------------------------------------------------------- 1 | package com.robin.lazy.cache.memory.impl.ext; 2 | 3 | import java.util.LinkedHashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * Static library version of {@link android.util.LruCache}. Used to write apps 8 | * that run on API levels prior to 12. When running on API level 12 or above, 9 | * this implementation is still used; it does not try to switch to the 10 | * framework's implementation. See the framework SDK documentation for a class 11 | * overview. 12 | */ 13 | 14 | public class LruCache { 15 | private final LinkedHashMap map; 16 | 17 | /** Size of this cache in units. Not necessarily the number of elements. */ 18 | private int size; 19 | private int maxSize; 20 | 21 | private int putCount; 22 | private int createCount; 23 | private int evictionCount; 24 | private int hitCount; 25 | private int missCount; 26 | 27 | /** 28 | * @param maxSize for caches that do not override {@link #sizeOf}, this is 29 | * the maximum number of entries in the cache. For all other caches, 30 | * this is the maximum sum of the sizes of the entries in this cache. 31 | */ 32 | public LruCache(int maxSize) { 33 | if (maxSize <= 0) { 34 | throw new IllegalArgumentException("maxSize <= 0"); 35 | } 36 | this.maxSize = maxSize; 37 | this.map = new LinkedHashMap(0, 0.75f, true); 38 | } 39 | 40 | /** 41 | * Sets the size of the cache. 42 | * 43 | * @param maxSize The new maximum size. 44 | */ 45 | public void resize(int maxSize) { 46 | if (maxSize <= 0) { 47 | throw new IllegalArgumentException("maxSize <= 0"); 48 | } 49 | 50 | synchronized (this) { 51 | this.maxSize = maxSize; 52 | } 53 | trimToSize(maxSize); 54 | } 55 | 56 | /** 57 | * Returns the value for {@code key} if it exists in the cache or can be 58 | * created by {@code #create}. If a value was returned, it is moved to the 59 | * head of the queue. This returns null if a value is not cached and cannot 60 | * be created. 61 | */ 62 | public final V get(K key) { 63 | if (key == null) { 64 | throw new NullPointerException("key == null"); 65 | } 66 | 67 | V mapValue; 68 | synchronized (this) { 69 | mapValue = map.get(key); 70 | if (mapValue != null) { 71 | hitCount++; 72 | return mapValue; 73 | } 74 | missCount++; 75 | } 76 | 77 | /* 78 | * Attempt to create a value. This may take a long time, and the map 79 | * may be different when create() returns. If a conflicting value was 80 | * added to the map while create() was working, we leave that value in 81 | * the map and release the created value. 82 | */ 83 | 84 | V createdValue = create(key); 85 | if (createdValue == null) { 86 | return null; 87 | } 88 | 89 | synchronized (this) { 90 | createCount++; 91 | mapValue = map.put(key, createdValue); 92 | 93 | if (mapValue != null) { 94 | // There was a conflict so undo that last put 95 | map.put(key, mapValue); 96 | } else { 97 | size += safeSizeOf(key, createdValue); 98 | } 99 | } 100 | 101 | if (mapValue != null) { 102 | entryRemoved(false, key, createdValue, mapValue); 103 | return mapValue; 104 | } else { 105 | trimToSize(maxSize); 106 | return createdValue; 107 | } 108 | } 109 | 110 | /** 111 | * Caches {@code value} for {@code key}. The value is moved to the head of 112 | * the queue. 113 | * 114 | * @return the previous value mapped by {@code key}. 115 | */ 116 | public final V put(K key, V value) { 117 | if (key == null || value == null) { 118 | throw new NullPointerException("key == null || value == null"); 119 | } 120 | 121 | V previous; 122 | synchronized (this) { 123 | putCount++; 124 | size += safeSizeOf(key, value); 125 | previous = map.put(key, value); 126 | if (previous != null) { 127 | size -= safeSizeOf(key, previous); 128 | } 129 | } 130 | 131 | if (previous != null) { 132 | entryRemoved(false, key, previous, value); 133 | } 134 | 135 | trimToSize(maxSize); 136 | return previous; 137 | } 138 | 139 | /** 140 | * Remove the eldest entries until the total of remaining entries is at or 141 | * below the requested size. 142 | * 143 | * @param maxSize the maximum size of the cache before returning. May be -1 144 | * to evict even 0-sized elements. 145 | */ 146 | public void trimToSize(int maxSize) { 147 | while (true) { 148 | K key; 149 | V value; 150 | synchronized (this) { 151 | if (size < 0 || (map.isEmpty() && size != 0)) { 152 | throw new IllegalStateException(getClass().getName() 153 | + ".sizeOf() is reporting inconsistent results!"); 154 | } 155 | 156 | if (size <= maxSize || map.isEmpty()) { 157 | break; 158 | } 159 | 160 | Map.Entry toEvict = map.entrySet().iterator().next(); 161 | key = toEvict.getKey(); 162 | value = toEvict.getValue(); 163 | map.remove(key); 164 | size -= safeSizeOf(key, value); 165 | evictionCount++; 166 | } 167 | 168 | entryRemoved(true, key, value, null); 169 | } 170 | } 171 | 172 | /** 173 | * Removes the entry for {@code key} if it exists. 174 | * 175 | * @return the previous value mapped by {@code key}. 176 | */ 177 | public final V remove(K key) { 178 | if (key == null) { 179 | throw new NullPointerException("key == null"); 180 | } 181 | 182 | V previous; 183 | synchronized (this) { 184 | previous = map.remove(key); 185 | if (previous != null) { 186 | size -= safeSizeOf(key, previous); 187 | } 188 | } 189 | 190 | if (previous != null) { 191 | entryRemoved(false, key, previous, null); 192 | } 193 | 194 | return previous; 195 | } 196 | 197 | /** 198 | * Called for entries that have been evicted or removed. This method is 199 | * invoked when a value is evicted to make space, removed by a call to 200 | * {@link #remove}, or replaced by a call to {@link #put}. The default 201 | * implementation does nothing. 202 | * 203 | *

The method is called without synchronization: other threads may 204 | * access the cache while this method is executing. 205 | * 206 | * @param evicted true if the entry is being removed to make space, false 207 | * if the removal was caused by a {@link #put} or {@link #remove}. 208 | * @param newValue the new value for {@code key}, if it exists. If non-null, 209 | * this removal was caused by a {@link #put}. Otherwise it was caused by 210 | * an eviction or a {@link #remove}. 211 | */ 212 | protected void entryRemoved(boolean evicted, K key, V oldValue, V newValue) {} 213 | 214 | /** 215 | * Called after a cache miss to compute a value for the corresponding key. 216 | * Returns the computed value or null if no value can be computed. The 217 | * default implementation returns null. 218 | * 219 | *

The method is called without synchronization: other threads may 220 | * access the cache while this method is executing. 221 | * 222 | *

If a value for {@code key} exists in the cache when this method 223 | * returns, the created value will be released with {@link #entryRemoved} 224 | * and discarded. This can occur when multiple threads request the same key 225 | * at the same time (causing multiple values to be created), or when one 226 | * thread calls {@link #put} while another is creating a value for the same 227 | * key. 228 | */ 229 | protected V create(K key) { 230 | return null; 231 | } 232 | 233 | private int safeSizeOf(K key, V value) { 234 | int result = sizeOf(key, value); 235 | if (result < 0) { 236 | throw new IllegalStateException("Negative size: " + key + "=" + value); 237 | } 238 | return result; 239 | } 240 | 241 | /** 242 | * Returns the size of the entry for {@code key} and {@code value} in 243 | * user-defined units. The default implementation returns 1 so that size 244 | * is the number of entries and max size is the maximum number of entries. 245 | * 246 | *

An entry's size must not change while it is in the cache. 247 | */ 248 | protected int sizeOf(K key, V value) { 249 | return 1; 250 | } 251 | 252 | /** 253 | * Clear the cache, calling {@link #entryRemoved} on each removed entry. 254 | */ 255 | public final void evictAll() { 256 | trimToSize(-1); // -1 will evict 0-sized elements 257 | } 258 | 259 | /** 260 | * For caches that do not override {@link #sizeOf}, this returns the number 261 | * of entries in the cache. For all other caches, this returns the sum of 262 | * the sizes of the entries in this cache. 263 | */ 264 | public synchronized final int size() { 265 | return size; 266 | } 267 | 268 | /** 269 | * For caches that do not override {@link #sizeOf}, this returns the maximum 270 | * number of entries in the cache. For all other caches, this returns the 271 | * maximum sum of the sizes of the entries in this cache. 272 | */ 273 | public synchronized final int maxSize() { 274 | return maxSize; 275 | } 276 | 277 | /** 278 | * Returns the number of times {@link #get} returned a value that was 279 | * already present in the cache. 280 | */ 281 | public synchronized final int hitCount() { 282 | return hitCount; 283 | } 284 | 285 | /** 286 | * Returns the number of times {@link #get} returned null or required a new 287 | * value to be created. 288 | */ 289 | public synchronized final int missCount() { 290 | return missCount; 291 | } 292 | 293 | /** 294 | * Returns the number of times {@link #create(Object)} returned a value. 295 | */ 296 | public synchronized final int createCount() { 297 | return createCount; 298 | } 299 | 300 | /** 301 | * Returns the number of times {@link #put} was called. 302 | */ 303 | public synchronized final int putCount() { 304 | return putCount; 305 | } 306 | 307 | /** 308 | * Returns the number of values that have been evicted. 309 | */ 310 | public synchronized final int evictionCount() { 311 | return evictionCount; 312 | } 313 | 314 | /** 315 | * Returns a copy of the current contents of the cache, ordered from least 316 | * recently accessed to most recently accessed. 317 | */ 318 | public synchronized final Map snapshot() { 319 | return new LinkedHashMap(map); 320 | } 321 | 322 | @Override public synchronized final String toString() { 323 | int accesses = hitCount + missCount; 324 | int hitPercent = accesses != 0 ? (100 * hitCount / accesses) : 0; 325 | return String.format("LruCache[maxSize=%d,hits=%d,misses=%d,hitRate=%d%%]", 326 | maxSize, hitCount, missCount, hitPercent); 327 | } 328 | } 329 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/process/CacheDataProcess.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: CacheDataProcess.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2015年12月14日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache.process; 13 | /** 14 | * 缓存数据加工接口 15 | * 16 | * @author jiangyufeng 17 | * @version [版本号, 2015年12月14日] 18 | * @param 范型 19 | * @see [相关类/方法] 20 | * @since [产品/模块版本] 21 | */ 22 | public interface CacheDataProcess { 23 | 24 | /** 25 | * 加工缓存的数据 26 | * @param data 27 | * @return 返回加工处理后的数据 28 | * V 29 | * @see [类、类#方法、类#成员] 30 | */ 31 | V process(V data); 32 | } 33 | 34 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/process/DefaultCacheDataProcess.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: DefaultCacheDataProcess.java 3 | * 版 权: Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: jiangyufeng 6 | * 修改时间: 2016年3月17日 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.cache.process; 13 | /** 14 | * 默认的缓存数据加工处理器 15 | * 16 | * @author jiangyufeng 17 | * @version [版本号, 2016年3月17日] 18 | * @param 19 | * @see [相关类/方法] 20 | * @since [产品/模块版本] 21 | */ 22 | public class DefaultCacheDataProcess implements CacheDataProcess{ 23 | 24 | @Override 25 | public V process(V data) { 26 | return data; 27 | } 28 | 29 | } 30 | 31 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/util/DiskCacheUtils.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2011-2014 Sergey Tarasevich 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *******************************************************************************/ 16 | package com.robin.lazy.cache.util; 17 | 18 | import android.content.Context; 19 | 20 | import com.robin.lazy.cache.disk.DiskCache; 21 | import com.robin.lazy.cache.disk.impl.BaseDiskCache; 22 | import com.robin.lazy.cache.disk.impl.ext.LruDiskCache; 23 | import com.robin.lazy.cache.disk.naming.FileNameGenerator; 24 | import com.robin.lazy.cache.disk.naming.HashCodeFileNameGenerator; 25 | import com.robin.lazy.cache.disk.write.StringWriteInDisk; 26 | import com.robin.lazy.cache.util.log.CacheLog; 27 | import com.robin.lazy.util.StorageUtils; 28 | 29 | import java.io.File; 30 | import java.io.IOException; 31 | 32 | /** 33 | * 磁盘缓存相关工具 34 | * 35 | * @author jiangyufeng 36 | * @version [版本号, 2015年12月15日] 37 | * @see [相关类/方法] 38 | * @since [产品/模块版本] 39 | */ 40 | public final class DiskCacheUtils { 41 | 42 | private final static String LOG_TAG=DiskCacheUtils.class.getSimpleName(); 43 | 44 | private DiskCacheUtils() { 45 | } 46 | 47 | /** 48 | * 创建一个文件名称转换器 49 | * @return 50 | */ 51 | public static FileNameGenerator createFileNameGenerator() { 52 | return new HashCodeFileNameGenerator(); 53 | } 54 | 55 | /** 56 | * Creates default implementation of {@link DiskCache} depends on incoming 57 | * parameters 58 | * @param diskCacheSize 可使用磁盘最大大小(单位byte,字节) 59 | */ 60 | public static DiskCache createDiskCache(Context context, 61 | FileNameGenerator diskCacheFileNameGenerator, long diskCacheSize, 62 | int diskCacheFileCount) { 63 | File reserveCacheDir = createReserveDiskCacheDir(context); 64 | if (diskCacheSize > 0 || diskCacheFileCount > 0) { 65 | File individualCacheDir = StorageUtils 66 | .getIndividualCacheDirectory(context); 67 | try { 68 | return new LruDiskCache(individualCacheDir, reserveCacheDir, 69 | diskCacheFileNameGenerator, diskCacheSize, 70 | diskCacheFileCount); 71 | } catch (IOException e) { 72 | CacheLog.e(LOG_TAG, "获取LruDiskCache错误",e); 73 | // continue and create unlimited cache 74 | } 75 | } 76 | File cacheDir = StorageUtils.getCacheDirectory(context); 77 | return new BaseDiskCache(cacheDir, reserveCacheDir, 78 | diskCacheFileNameGenerator); 79 | } 80 | 81 | /** 82 | * Creates reserve disk cache folder which will be used if primary disk 83 | * cache folder becomes unavailable 84 | */ 85 | private static File createReserveDiskCacheDir(Context context) { 86 | File cacheDir = StorageUtils.getCacheDirectory(context, false); 87 | File individualDir = new File(cacheDir, "lazy-cache"); 88 | if (individualDir.exists() || individualDir.mkdir()) { 89 | cacheDir = individualDir; 90 | } 91 | return cacheDir; 92 | } 93 | 94 | /** 95 | * Returns {@link File} of cached key or null if key was not cached 96 | * in disk cache 97 | */ 98 | public static File findInCache(String key, DiskCache diskCache) { 99 | File file = diskCache.getFile(key); 100 | return file != null && file.exists() ? file : null; 101 | } 102 | 103 | /** 104 | * Removed cached key file from disk cache (if key was cached in disk cache 105 | * before) 106 | * 107 | * @return true - if cached key file existed and was deleted; 108 | * false - otherwise. 109 | */ 110 | public static boolean removeFromCache(String key, DiskCache diskCache) { 111 | File file = diskCache.getFile(key); 112 | return file != null && file.exists() && file.delete(); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/util/MemoryCacheUtils.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2011-2014 Sergey Tarasevich 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | *******************************************************************************/ 16 | package com.robin.lazy.cache.util; 17 | 18 | import android.annotation.TargetApi; 19 | import android.app.ActivityManager; 20 | import android.content.Context; 21 | import android.content.pm.ApplicationInfo; 22 | import android.os.Build; 23 | 24 | import com.robin.lazy.cache.memory.EntryRemovedProcess; 25 | import com.robin.lazy.cache.memory.MemoryCache; 26 | import com.robin.lazy.cache.memory.SizeOfCacheCalculator; 27 | import com.robin.lazy.cache.memory.impl.EntryRemovedProcessMemoryCache; 28 | import com.robin.lazy.cache.memory.impl.LruMemoryCache; 29 | import com.robin.lazy.cache.memory.impl.SizeOfMemoryCache; 30 | 31 | import java.util.ArrayList; 32 | import java.util.List; 33 | 34 | /** 35 | * 内存缓存工具 36 | * 37 | * @author jiangyufeng 38 | * @version [版本号, 2015年12月15日] 39 | * @see [相关类/方法] 40 | * @since [产品/模块版本] 41 | */ 42 | public final class MemoryCacheUtils { 43 | 44 | private MemoryCacheUtils() { 45 | } 46 | 47 | /** 48 | * 创建一个有固定大小的内存缓存操作工具 49 | * 50 | * @param memoryCacheSize 51 | * 内存缓存的最大限度(单位兆MB) 52 | * @param calculator 53 | * 单个内存缓存占用内存大小计算器 54 | * @return SizeOfMemoryCache 55 | * @throws 56 | * @see [类、类#方法、类#成员] 57 | */ 58 | public static SizeOfMemoryCache createMemoryCache( 59 | int memoryCacheSize, SizeOfCacheCalculator calculator) { 60 | if (memoryCacheSize <= 0) { 61 | new NullPointerException("memoryCacheSize小于0"); 62 | } 63 | return new SizeOfMemoryCache(memoryCacheSize, calculator); 64 | } 65 | 66 | /** 67 | * 创建一个有固定大小的内存缓存操作工具 68 | * 69 | * @param context 70 | * @param ratio 71 | * 占当前可用内存的比例(最大为1) 72 | * @param calculator 73 | * 单个内存缓存占用内存大小计算器 74 | * @return SizeOfMemoryCache 75 | * @throws 76 | * @see [类、类#方法、类#成员] 77 | */ 78 | public static SizeOfMemoryCache createMemoryCache(Context context, 79 | float ratio, SizeOfCacheCalculator calculator) { 80 | int memoryCacheSize = 0; 81 | ActivityManager am = (ActivityManager) context 82 | .getSystemService(Context.ACTIVITY_SERVICE); 83 | int memoryClass = am.getMemoryClass();// 获取可用内存大小(单位MB) 84 | if (hasHoneycomb() && isLargeHeap(context)) { 85 | memoryClass = getLargeMemoryClass(am); 86 | } 87 | memoryCacheSize = (int) (1024 * 1024 * memoryClass * ratio); 88 | return new SizeOfMemoryCache(memoryCacheSize, calculator); 89 | } 90 | 91 | /** 92 | * 创建能够自定义处理被回收的数据的内存缓存类 93 | * 94 | * @param maxSize 可以储存的缓存数据数量最大上限(单位未知) 95 | * @param entryRemovedProcess 删除处理者 96 | * @return LruMemoryCache 97 | * @throws 98 | * @see [类、类#方法、类#成员] 99 | */ 100 | public static EntryRemovedProcessMemoryCache createLruMemoryCache(int maxSize, 101 | EntryRemovedProcess entryRemovedProcess) { 102 | return new EntryRemovedProcessMemoryCache(maxSize,entryRemovedProcess); 103 | } 104 | 105 | /** 106 | * 创建默认的Lru内存缓存类 107 | * 108 | * @param maxSize 109 | * 可以储存的缓存数据数量最大上限(单位未知) 110 | * @return LruMemoryCache 111 | * @throws 112 | * @see [类、类#方法、类#成员] 113 | */ 114 | public static LruMemoryCache createLruMemoryCache(int maxSize) { 115 | return new LruMemoryCache(maxSize); 116 | } 117 | 118 | private static boolean hasHoneycomb() { 119 | return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB; 120 | } 121 | 122 | @TargetApi(Build.VERSION_CODES.HONEYCOMB) 123 | private static boolean isLargeHeap(Context context) { 124 | return (context.getApplicationInfo().flags & ApplicationInfo.FLAG_LARGE_HEAP) != 0; 125 | } 126 | 127 | /** 128 | * 获取可用内存大小(单位MB) 129 | * 130 | * @param am 131 | * @return int 132 | * @throws 133 | * @see [类、类#方法、类#成员] 134 | */ 135 | @TargetApi(Build.VERSION_CODES.HONEYCOMB) 136 | private static int getLargeMemoryClass(ActivityManager am) { 137 | return am.getLargeMemoryClass(); 138 | } 139 | 140 | 141 | /** 142 | * 根据key查找对应的数据 143 | * @param key 144 | * @param memoryCache 145 | * @param 146 | * @return 147 | */ 148 | public static List findCachedForkey(String key, 149 | MemoryCache memoryCache) { 150 | List values = new ArrayList(); 151 | for (String k : memoryCache.keys()) { 152 | if (k.startsWith(key)) { 153 | V value = memoryCache.get(k); 154 | values.add(value); 155 | } 156 | } 157 | return values; 158 | } 159 | 160 | /** 161 | * 根据key查找对应的数据 162 | * @param key 163 | * @param memoryCache 164 | * @return 165 | */ 166 | public static List findCacheKeysForkey(String key, 167 | MemoryCache memoryCache) { 168 | List values = new ArrayList(); 169 | for (String k : memoryCache.keys()) { 170 | if (k.startsWith(key)) { 171 | values.add(k); 172 | } 173 | } 174 | return values; 175 | } 176 | 177 | /** 178 | * 根据key删除对应的数据 179 | * @param key 180 | * @param memoryCache 181 | */ 182 | public static void removeFromCache(String key, MemoryCache memoryCache) { 183 | List keysToRemove = new ArrayList(); 184 | for (String k : memoryCache.keys()) { 185 | if (k.startsWith(key)) { 186 | keysToRemove.add(k); 187 | } 188 | } 189 | for (String keyToRemove : keysToRemove) { 190 | memoryCache.remove(keyToRemove); 191 | } 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/util/log/AndroidLog.java: -------------------------------------------------------------------------------- 1 | package com.robin.lazy.cache.util.log; 2 | 3 | import android.util.Log; 4 | 5 | /** 6 | * @desc: android官方日志打印的实现 7 | * @projectName:LazyNetForAndroid 8 | * @className: AndroidLog 9 | * @author: jiangyufeng 10 | * @createTime: 2018/10/17 下午2:39 11 | */ 12 | public class AndroidLog implements ILog { 13 | /** 14 | * VERBOSE类型日志 15 | */ 16 | private final static int VERBOSE = 1; 17 | 18 | /** 19 | * debug类型日志 20 | */ 21 | private final static int DEBUG = 2; 22 | 23 | /** 24 | * info类型日志 25 | */ 26 | private final static int INFO = 3; 27 | 28 | /** 29 | * warn类型日志 30 | */ 31 | private final static int WARN = 4; 32 | 33 | /** 34 | * error类型日志 35 | */ 36 | private final static int ERROR = 5; 37 | 38 | /** 39 | * ASSERT类型日志 40 | */ 41 | private final static int ASSERT = 6; 42 | /** 43 | * 一次日志最大打印长度 44 | */ 45 | private final static int MAX_LENGTH = 3600; 46 | 47 | @Override 48 | public void d(String tag, String message) { 49 | log(DEBUG,tag,message,null); 50 | } 51 | 52 | @Override 53 | public void d(String tag, String message, Throwable throwable) { 54 | log(DEBUG,tag,message,throwable); 55 | } 56 | 57 | @Override 58 | public void e(String tag, String message) { 59 | log(ERROR,tag,message,null); 60 | } 61 | 62 | @Override 63 | public void e(String tag, String message, Throwable throwable) { 64 | log(ERROR,tag,message,throwable); 65 | } 66 | 67 | @Override 68 | public void w(String tag, String message) { 69 | log(WARN,tag,message,null); 70 | } 71 | 72 | @Override 73 | public void w(String tag, String message, Throwable throwable) { 74 | log(WARN,tag,message,throwable); 75 | } 76 | 77 | @Override 78 | public void i(String tag, String message) { 79 | log(INFO,tag,message,null); 80 | } 81 | 82 | @Override 83 | public void i(String tag, String message, Throwable throwable) { 84 | log(INFO,tag,message,throwable); 85 | } 86 | 87 | @Override 88 | public void v(String tag, String message) { 89 | log(VERBOSE,tag,message,null); 90 | } 91 | 92 | @Override 93 | public void v(String tag, String message, Throwable throwable) { 94 | log(VERBOSE,tag,message,throwable); 95 | } 96 | 97 | @Override 98 | public void wtf(String tag, String message) { 99 | log(ASSERT,tag,message,null); 100 | } 101 | 102 | @Override 103 | public void wtf(String tag, String message, Throwable throwable) { 104 | log(ASSERT,tag,message,throwable); 105 | } 106 | 107 | /** 108 | * 日志输入方法 109 | * 110 | * @param logLevel 日志ji'b级别 111 | * @param tag 112 | * @param message 113 | * @param throwable 114 | */ 115 | private void log(int logLevel, String tag, String message, 116 | Throwable throwable) { 117 | while (message.length() > MAX_LENGTH) { 118 | print(logLevel,tag,message.substring(0, MAX_LENGTH),throwable); 119 | message = message.substring(MAX_LENGTH); 120 | } 121 | print(logLevel,tag,message,throwable); 122 | } 123 | 124 | /** 125 | * 最终打印方法 126 | * 127 | * @param logLevel 128 | * @param tag 129 | * @param message 130 | * @param throwable 131 | */ 132 | private void print(int logLevel, String tag, String message, 133 | Throwable throwable) { 134 | switch (logLevel) { 135 | case VERBOSE: 136 | if(throwable==null){ 137 | Log.v(tag, message); 138 | }else{ 139 | Log.v(tag, message,throwable); 140 | } 141 | break; 142 | case DEBUG: 143 | if(throwable==null){ 144 | Log.d(tag, message); 145 | }else { 146 | Log.d(tag, message,throwable); 147 | } 148 | break; 149 | case INFO: 150 | if(throwable==null){ 151 | Log.i(tag, message); 152 | }else { 153 | Log.i(tag, message,throwable); 154 | } 155 | break; 156 | case WARN: 157 | if(throwable==null){ 158 | Log.w(tag, message); 159 | }else{ 160 | Log.w(tag, message,throwable); 161 | } 162 | break; 163 | case ERROR: 164 | if(throwable==null){ 165 | Log.e(tag, message); 166 | }else { 167 | Log.e(tag, message,throwable); 168 | } 169 | break; 170 | case ASSERT: 171 | if(throwable==null){ 172 | Log.wtf(tag, message); 173 | }else{ 174 | Log.wtf(tag, message,throwable); 175 | } 176 | break; 177 | } 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/util/log/CacheLog.java: -------------------------------------------------------------------------------- 1 | package com.robin.lazy.cache.util.log; 2 | 3 | import android.text.TextUtils; 4 | 5 | import org.json.JSONArray; 6 | import org.json.JSONException; 7 | import org.json.JSONObject; 8 | 9 | /** 10 | * @desc: 日志打印的被委托者 11 | * @projectName:LazyNetForAndroid 12 | * @className: CacheLog 13 | * @author: jiangyufeng 14 | * @createTime: 2018/10/12 下午5:36 15 | */ 16 | public final class CacheLog { 17 | /** 18 | * It is used for json pretty print 19 | */ 20 | private static final int JSON_INDENT = 4; 21 | 22 | /*** 23 | * 是否是debug 24 | */ 25 | private static boolean isDebug=true; 26 | /*** 27 | * 委托者 28 | */ 29 | private static ILog delegate = new AndroidLog(); 30 | 31 | /** 32 | * 重置委托者 33 | * @param delegate 34 | */ 35 | public static void resetDelegate(ILog delegate) { 36 | CacheLog.delegate = delegate; 37 | } 38 | 39 | /** 40 | * 设置是否debug模式,debug才会输出日志,默认为true 41 | * @param isDebug 42 | */ 43 | public static void setIsDebug(boolean isDebug) { 44 | CacheLog.isDebug = isDebug; 45 | } 46 | 47 | public static void d(String tag, String message) { 48 | if (!isDebug)return; 49 | if (delegate == null) throw new NullPointerException("delegate may not be null"); 50 | delegate.d(tag,message); 51 | } 52 | 53 | public static void d(String tag, String message, Throwable throwable) { 54 | if (!isDebug)return; 55 | if (delegate == null) throw new NullPointerException("delegate may not be null"); 56 | delegate.d(tag,message,throwable); 57 | } 58 | 59 | public static void e(String tag, String message) { 60 | if (!isDebug)return; 61 | if (delegate == null) throw new NullPointerException("delegate may not be null"); 62 | delegate.e(tag,message); 63 | } 64 | 65 | public static void e(String tag, String message, Throwable throwable) { 66 | if (!isDebug)return; 67 | if (delegate == null) throw new NullPointerException("delegate may not be null"); 68 | delegate.e(tag,message,throwable); 69 | } 70 | 71 | public static void w(String tag, String message) { 72 | if (!isDebug)return; 73 | if (delegate == null) throw new NullPointerException("delegate may not be null"); 74 | delegate.w(tag,message); 75 | } 76 | 77 | public static void w(String tag, String message, Throwable throwable) { 78 | if (!isDebug)return; 79 | if (delegate == null) throw new NullPointerException("delegate may not be null"); 80 | delegate.w(tag,message,throwable); 81 | } 82 | 83 | public static void i(String tag, String message) { 84 | if (!isDebug)return; 85 | if (delegate == null) throw new NullPointerException("delegate may not be null"); 86 | delegate.i(tag,message); 87 | } 88 | 89 | public static void i(String tag, String message, Throwable throwable) { 90 | if (!isDebug)return; 91 | if (delegate == null) throw new NullPointerException("delegate may not be null"); 92 | delegate.i(tag,message,throwable); 93 | } 94 | 95 | public static void v(String tag, String message) { 96 | if (!isDebug)return; 97 | if (delegate == null) throw new NullPointerException("delegate may not be null"); 98 | delegate.v(tag,message); 99 | } 100 | 101 | public static void v(String tag, String message, Throwable throwable) { 102 | if (!isDebug)return; 103 | if (delegate == null) throw new NullPointerException("delegate may not be null"); 104 | delegate.v(tag,message,throwable); 105 | } 106 | 107 | public static void wtf(String tag, String message) { 108 | if (!isDebug)return; 109 | if (delegate == null) throw new NullPointerException("delegate may not be null"); 110 | delegate.wtf(tag,message); 111 | } 112 | 113 | public static void wtf(String tag, String message, Throwable throwable) { 114 | if (!isDebug)return; 115 | if (delegate == null) throw new NullPointerException("delegate may not be null"); 116 | delegate.wtf(tag, message, throwable); 117 | } 118 | 119 | /** 120 | * 打印json数据日志 121 | * @param tag 122 | * @param json 123 | */ 124 | public static void json(String tag, String json) { 125 | if (!isDebug)return; 126 | if (delegate == null) throw new NullPointerException("delegate may not be null"); 127 | if (TextUtils.isEmpty(json)) { 128 | d(tag,"Empty/Null json content"); 129 | return; 130 | } 131 | try { 132 | if (json.startsWith("{")) { 133 | JSONObject jsonObject = new JSONObject(json); 134 | String message = jsonObject.toString(JSON_INDENT); 135 | d(tag,message); 136 | return; 137 | } 138 | if (json.startsWith("[")) { 139 | JSONArray jsonArray = new JSONArray(json); 140 | String message = jsonArray.toString(JSON_INDENT); 141 | d(tag,message); 142 | } 143 | } catch (JSONException e) { 144 | e(tag,e.getCause().getMessage() + "\n" + json); 145 | } 146 | } 147 | 148 | } 149 | -------------------------------------------------------------------------------- /LazyCache/src/main/java/com/robin/lazy/cache/util/log/ILog.java: -------------------------------------------------------------------------------- 1 | package com.robin.lazy.cache.util.log; 2 | 3 | /** 4 | * @desc: 日志输出接口 5 | * @projectName:LazyNetForAndroid 6 | * @className: ILog 7 | * @author: jiangyufeng 8 | * @createTime: 2018/10/12 下午5:35 9 | */ 10 | public interface ILog { 11 | 12 | void d(String tag, String message); 13 | 14 | void d(String tag, String message, Throwable throwable); 15 | 16 | void e(String tag, String message); 17 | 18 | void e(String tag, String message, Throwable throwable); 19 | 20 | void w(String tag, String message); 21 | 22 | void w(String tag, String message, Throwable throwable); 23 | 24 | void i(String tag, String message); 25 | 26 | void i(String tag, String message, Throwable throwable); 27 | 28 | void v(String tag, String message); 29 | 30 | void v(String tag, String message, Throwable throwable); 31 | 32 | void wtf(String tag, String message); 33 | 34 | void wtf(String tag, String message, Throwable throwable); 35 | } 36 | -------------------------------------------------------------------------------- /LazyCache/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | CacheLibrary 3 | 4 | -------------------------------------------------------------------------------- /LazyCache/src/test/java/com/robin/lazy/cache/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.robin.lazy.cache; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | @Test 12 | public void addition_isCorrect() throws Exception { 13 | assertEquals(4, 2 + 2); 14 | } 15 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | LazyCacheForAndroid 2 | ----------------------------------- 3 | # 项目介绍 4 | ### 项目地址 5 | * [LazyCacheForAndroid](https://github.com/Robin-jiangyufeng/LazyCacheForAndroid) 6 | ###版本 7 | * [![](https://jitpack.io/v/Robin-jiangyufeng/LazyCacheForAndroid.svg)](https://jitpack.io/#Robin-jiangyufeng/LazyCacheForAndroid) 8 | ### 介绍: 9 | * 这是一个android上的数据缓存框架,具有缓存和加载数据速度快,缓存数据类型全,能够实现任意缓存时间等优点 10 | 11 | ### 功能: 12 | * 1.目前已经实现的可以缓存String,Serialiable,Bitmap,InputStream,Bytes等类型数据,当然你也可以自己进行扩展实现自己需要缓存的类型数据 13 | * 2.支持多级缓存,目前已实现lru算法的磁盘缓存和lru算法的内存缓存,根据优先级进行缓存,当然你也可以扩展实现多级缓存,只要实现Cache接口,设置缓存优先级即可 14 | * 3.可以设置全局数据缓存的时间,也可以单独设置一条数据缓存的时间 15 | * 4.有更多功能 16 | 17 | ### 使用场景: 18 | * 1.替换SharePreference当做配置文件 19 | * 2.缓存网络数据,比如json,图片数据等 20 | * 3.自己想... 21 | 22 | # 使用方法 23 | ### 库引入方式 24 | * Gradle: 25 | ```` 26 | repositories { 27 | jcenter() 28 | maven {url 'https://dl.bintray.com/jiangyufeng/maven/'} 29 | } 30 | 31 | compile 'com.github.Robin-jiangyufeng:LazyCacheForAndroid:1.0.9' 32 | ```` 33 | * Maven: 34 | ```` 35 | 36 | com.robin.lazy.cache 37 | LazyCache 38 | 1.0.7 39 | pom 40 | 41 | ```` 42 | 43 | ### 所需权限 44 | ```java 45 | 46 | 47 | 48 | ``` 49 | 50 | ### 初始化 51 | * 想要直接使用CacheLoaderManager进行数据储存的话,请先进行初始化,初始化方式如下: 52 | ```java 53 | /*** 54 | * 初始化缓存的一些配置 55 | * 56 | * @param diskCacheFileNameGenerator 57 | * @param diskCacheSize 磁盘缓存大小 58 | * @param diskCacheFileCount 磁盘缓存文件的最大限度 59 | * @param maxMemorySize 内存缓存的大小 60 | * @return CacheLoaderConfiguration 61 | * @throws 62 | * @see [类、类#方法、类#成员] 63 | */ 64 | CacheLoaderManager.getInstance().init(Context context,FileNameGenerator diskCacheFileNameGenerator, long diskCacheSize, 65 | int diskCacheFileCount, int maxMemorySize); 66 | ``` 67 | ### 缓存数据 68 | * 以下代码只列举了储存String类型的数据,其它数据类型储存类似,具体请阅读 CacheLoaderManager.java 69 | ```java 70 | /** 71 | * save String到缓存 72 | * @param key 73 | * @param value 要缓存的值 74 | * @param maxLimitTime 缓存期限(单位分钟) 75 | * @return 是否保存成功 76 | * boolean 77 | * @throws 78 | * @see [类、类#方法、类#成员] 79 | */ 80 | CacheLoaderManager.getInstance().saveString(String key,String value,long maxLimitTime); 81 | ``` 82 | ### 加载缓存数据 83 | * 以下代码只列举了加载String类型的数据方法,其它数据加载类似,具体请阅读 CacheLoaderManager.java 84 | ```java 85 | /** 86 | * 加载String 87 | * @param key 88 | * @return 等到缓存数据 89 | * String 90 | * @throws 91 | * @see [类、类#方法、类#成员] 92 | */ 93 | CacheLoaderManager.getInstance().loadString(String key); 94 | ``` 95 | ### 其它 96 | * 上面介绍的是很小的一部分已经实现的功能,其中有还有很多功能可以高度定制,扩展性很强,更多功能待你发现; 97 | 98 | # 关于作者Robin 99 | * 屌丝程序员 100 | * GitHub: [Robin-jiangyufeng](https://github.com/Robin-jiangyufeng) 101 | * QQ:429257411 102 | * 交流QQ群 236395044 103 | -------------------------------------------------------------------------------- /Sample/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /Sample/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 33 5 | 6 | defaultConfig { 7 | applicationId "com.robin.lazy.sample" 8 | minSdkVersion 14 9 | targetSdkVersion 33 10 | versionCode 11 11 | versionName "1.1" 12 | multiDexEnabled true 13 | //ADD THIS LINE: 14 | testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' 15 | } 16 | 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | 24 | lintOptions { 25 | abortOnError false 26 | } 27 | 28 | dexOptions { 29 | incremental true 30 | javaMaxHeapSize "4g" 31 | } 32 | } 33 | 34 | dependencies { 35 | implementation fileTree(include: ['*.jar'], dir: 'libs') 36 | implementation 'androidx.appcompat:appcompat:1.3.0' 37 | implementation 'com.google.android.material:material:1.4.0' 38 | testImplementation 'junit:junit:4.12' 39 | implementation 'androidx.multidex:multidex:2.0.1' 40 | //ADD THESE LINES: 41 | //noinspection GradleCompatible 42 | testImplementation 'androidx.test.ext:junit:1.1.1' 43 | testImplementation 'androidx.test:rules:1.1.1' 44 | testImplementation 'androidx.annotation:annotation:1.0.0' 45 | implementation 'androidx.test.espresso:espresso-core:3.4.0' 46 | implementation 'in.srain.cube:ultra-ptr:1.0.11' 47 | implementation project(':LazyCache') 48 | } 49 | -------------------------------------------------------------------------------- /Sample/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Volumes/Work/androidIDE/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /Sample/src/androidTest/java/com/robin/lazy/sample/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.robin.lazy.sample; 2 | 3 | import android.test.ApplicationTestCase; 4 | 5 | /** 6 | * Testing Fundamentals 7 | */ 8 | public class ApplicationTest extends ApplicationTestCase { 9 | public ApplicationTest() { 10 | super(App.class); 11 | } 12 | } -------------------------------------------------------------------------------- /Sample/src/androidTest/java/com/robin/lazy/sample/MainActivityTest.java: -------------------------------------------------------------------------------- 1 | package com.robin.lazy.sample; 2 | 3 | import androidx.test.espresso.Espresso; 4 | import androidx.test.espresso.action.ViewActions; 5 | import androidx.test.espresso.core.deps.guava.util.concurrent.Uninterruptibles; 6 | import androidx.test.espresso.matcher.ViewMatchers; 7 | import androidx.test.rule.ActivityTestRule; 8 | import androidx.test.ext.junit.runners.AndroidJUnit4; 9 | import android.test.suitebuilder.annotation.LargeTest; 10 | 11 | import org.junit.Before; 12 | import org.junit.Rule; 13 | import org.junit.Test; 14 | import org.junit.runner.RunWith; 15 | 16 | import java.util.concurrent.TimeUnit; 17 | 18 | /** 19 | * 文 件 名: MainActivityTest.java 20 | * 版 权: Technologies Co., Ltd. Copyright YYYY-YYYY, All rights reserved 21 | * 描 述: <描述> 22 | * 修 改 人: 江钰锋 00501 23 | * 修改时间: 16/6/6 24 | * 跟踪单号: <跟踪单号> 25 | * 修改单号: <修改单号> 26 | * 修改内容: <修改内容> 27 | */ 28 | @RunWith(AndroidJUnit4.class) 29 | @LargeTest 30 | public class MainActivityTest { 31 | 32 | @Rule 33 | public ActivityTestRule activityTestRule = new ActivityTestRule(MainActivity.class); 34 | 35 | @Before 36 | public void setUp() throws Exception { 37 | 38 | } 39 | 40 | @Test 41 | public void testOnCreate() throws Exception { 42 | Espresso.onView(ViewMatchers.withId(R.id.buttonSave)).perform(ViewActions.click()); 43 | Uninterruptibles.sleepUninterruptibly(5, TimeUnit.SECONDS); 44 | Espresso.onView(ViewMatchers.withId(R.id.buttonLoad)).perform(ViewActions.click()); 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /Sample/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 9 | 16 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Sample/src/main/assets/province.json: -------------------------------------------------------------------------------- 1 | { 2 | "province": [ 3 | { 4 | "areaid": "100000", 5 | "areaname": "全国" 6 | }, 7 | { 8 | "areaid": "110000", 9 | "areaname": "北京市" 10 | }, 11 | { 12 | "areaid": "120000", 13 | "areaname": "天津市" 14 | }, 15 | { 16 | "areaid": "130000", 17 | "areaname": "河北省" 18 | }, 19 | { 20 | "areaid": "140000", 21 | "areaname": "山西省" 22 | }, 23 | { 24 | "areaid": "150000", 25 | "areaname": "内蒙古自治区" 26 | }, 27 | { 28 | "areaid": "210000", 29 | "areaname": "辽宁省" 30 | }, 31 | { 32 | "areaid": "220000", 33 | "areaname": "吉林省" 34 | }, 35 | { 36 | "areaid": "230000", 37 | "areaname": "黑龙江省" 38 | }, 39 | { 40 | "areaid": "310000", 41 | "areaname": "上海市" 42 | }, 43 | { 44 | "areaid": "320000", 45 | "areaname": "江苏省" 46 | }, 47 | { 48 | "areaid": "330000", 49 | "areaname": "浙江省" 50 | }, 51 | { 52 | "areaid": "340000", 53 | "areaname": "安徽省" 54 | }, 55 | { 56 | "areaid": "350000", 57 | "areaname": "福建省" 58 | }, 59 | { 60 | "areaid": "360000", 61 | "areaname": "江西省" 62 | }, 63 | { 64 | "areaid": "370000", 65 | "areaname": "山东省" 66 | }, 67 | { 68 | "areaid": "410000", 69 | "areaname": "河南省" 70 | }, 71 | { 72 | "areaid": "420000", 73 | "areaname": "湖北省" 74 | }, 75 | { 76 | "areaid": "430000", 77 | "areaname": "湖南省" 78 | }, 79 | { 80 | "areaid": "440000", 81 | "areaname": "广东省" 82 | }, 83 | { 84 | "areaid": "450000", 85 | "areaname": "广西壮族自治区" 86 | }, 87 | { 88 | "areaid": "460000", 89 | "areaname": "海南省" 90 | }, 91 | { 92 | "areaid": "500000", 93 | "areaname": "重庆市" 94 | }, 95 | { 96 | "areaid": "510000", 97 | "areaname": "四川省" 98 | }, 99 | { 100 | "areaid": "520000", 101 | "areaname": "贵州省" 102 | }, 103 | { 104 | "areaid": "530000", 105 | "areaname": "云南省" 106 | }, 107 | { 108 | "areaid": "540000", 109 | "areaname": "西藏自治区" 110 | }, 111 | { 112 | "areaid": "610000", 113 | "areaname": "陕西省" 114 | }, 115 | { 116 | "areaid": "620000", 117 | "areaname": "甘肃省" 118 | }, 119 | { 120 | "areaid": "630000", 121 | "areaname": "青海省" 122 | }, 123 | { 124 | "areaid": "640000", 125 | "areaname": "宁夏回族自治区" 126 | }, 127 | { 128 | "areaid": "650000", 129 | "areaname": "新疆维吾尔自治区" 130 | } 131 | ] 132 | } -------------------------------------------------------------------------------- /Sample/src/main/java/com/robin/lazy/sample/App.java: -------------------------------------------------------------------------------- 1 | /* 2 | * 文 件 名: App.java 3 | * 版 权: Technologies Co., Ltd. Copyright YYYY-YYYY, All rights reserved 4 | * 描 述: <描述> 5 | * 修 改 人: 江钰锋 00501 6 | * 修改时间: 16/6/3 7 | * 跟踪单号: <跟踪单号> 8 | * 修改单号: <修改单号> 9 | * 修改内容: <修改内容> 10 | */ 11 | 12 | package com.robin.lazy.sample; 13 | 14 | import android.app.Application; 15 | 16 | import com.robin.lazy.cache.CacheLoaderManager; 17 | import com.robin.lazy.cache.disk.naming.HashCodeFileNameGenerator; 18 | 19 | /** 20 | * <一句话功能简述> 21 | * <功能详细描述> 22 | * 23 | * @author 江钰锋 00501 24 | * @version [版本号, 16/6/3] 25 | * @see [相关类/方法] 26 | * @since [产品/模块版本] 27 | */ 28 | public class App extends Application { 29 | @Override 30 | public void onCreate() { 31 | super.onCreate(); 32 | CacheLoaderManager.getInstance().init(this, new HashCodeFileNameGenerator(), 1024 * 1024 * 8, 50, 20); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Sample/src/main/java/com/robin/lazy/sample/FileUtil.java: -------------------------------------------------------------------------------- 1 | package com.robin.lazy.sample; 2 | 3 | import android.content.Context; 4 | 5 | import java.io.ByteArrayOutputStream; 6 | import java.io.File; 7 | import java.io.FileNotFoundException; 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | 11 | /** 12 | * 文件工具 13 | * 14 | * @author jiangyufeng 15 | * @version [版本号, 2015年11月23日] 16 | * @see [相关类/方法] 17 | * @since [产品/模块版本] 18 | */ 19 | public class FileUtil { 20 | /** 21 | * 删除文件 22 | * 23 | * @param context 程序上下文 24 | * @param fileName 文件名,要在系统内保持唯一 25 | * @return boolean 存储成功的标志 26 | */ 27 | public static boolean deleteFile(Context context, String fileName) { 28 | return context.deleteFile(fileName); 29 | } 30 | 31 | /** 32 | * 文件是否存在 33 | * 34 | * @param context 35 | * @param fileName 36 | * @return 37 | */ 38 | public static boolean exists(Context context, String fileName) { 39 | return new File(context.getFilesDir(), fileName).exists(); 40 | } 41 | 42 | /** 43 | * 读取文本数据 44 | * 45 | * @param context 程序上下文 46 | * @param fileName 文件名 47 | * @return String, 读取到的文本内容,失败返回null 48 | */ 49 | public static String readAssets(Context context, String fileName) { 50 | InputStream is = null; 51 | String content = null; 52 | try { 53 | is = context.getAssets().open(fileName); 54 | if (is != null) { 55 | 56 | byte[] buffer = new byte[1024]; 57 | ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream(); 58 | while (true) { 59 | int readLength = is.read(buffer); 60 | if (readLength == -1) break; 61 | arrayOutputStream.write(buffer, 0, readLength); 62 | } 63 | is.close(); 64 | arrayOutputStream.close(); 65 | content = new String(arrayOutputStream.toByteArray()); 66 | 67 | } 68 | } catch (FileNotFoundException e) { 69 | e.printStackTrace(); 70 | } catch (IOException e) { 71 | e.printStackTrace(); 72 | content = null; 73 | } finally { 74 | try { 75 | if (is != null) is.close(); 76 | } catch (IOException ioe) { 77 | ioe.printStackTrace(); 78 | } 79 | } 80 | return content; 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /Sample/src/main/java/com/robin/lazy/sample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.robin.lazy.sample; 2 | 3 | import android.os.Bundle; 4 | import androidx.appcompat.app.AppCompatActivity; 5 | import android.text.TextUtils; 6 | import android.view.View; 7 | import android.widget.TextView; 8 | import android.widget.Toast; 9 | 10 | import com.robin.lazy.cache.CacheLoaderManager; 11 | 12 | import in.srain.cube.views.ptr.PtrDefaultHandler; 13 | import in.srain.cube.views.ptr.PtrFrameLayout; 14 | import in.srain.cube.views.ptr.PtrHandler; 15 | import in.srain.cube.views.ptr.header.StoreHouseHeader; 16 | import in.srain.cube.views.ptr.util.PtrLocalDisplay; 17 | 18 | public class MainActivity extends AppCompatActivity implements View.OnClickListener { 19 | 20 | private long lastTime; 21 | private TextView textView; 22 | 23 | @Override 24 | protected void onCreate(Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | View view= View.inflate(this,R.layout.activity_main,null); 27 | setContentView(view); 28 | findViewById(R.id.buttonSave).setOnClickListener(this); 29 | findViewById(R.id.buttonLoad).setOnClickListener(this); 30 | findViewById(R.id.buttonClear).setOnClickListener(this); 31 | textView=(TextView)findViewById(R.id.textView); 32 | } 33 | 34 | @Override 35 | public void onClick(View v) { 36 | int id = v.getId(); 37 | if (id == R.id.buttonSave) { 38 | //把数据存入缓存需要操作io流,有对io的操作都是比较耗时的,最好都在子线程完成. 39 | //android 理想的fps是大于等于60(16s/帧),这种情况应用操作起来才会感觉不到卡顿 40 | //尽管测出来存储缓存数据使用的时间在6s左右,但是为了性能考虑,最好在子线程中操作 41 | new Thread(new Runnable() { 42 | @Override 43 | public void run() { 44 | runOnUiThread(new Runnable() { 45 | @Override 46 | public void run() { 47 | String area_strs = FileUtil.readAssets(MainActivity.this, "province.json"); 48 | lastTime = System.currentTimeMillis(); 49 | CacheLoaderManager.getInstance().saveString("area_strs", area_strs, 0); 50 | CacheLoaderManager.getInstance().saveString("area_strs1", area_strs, 0); 51 | textView.setText("保存数据用时:"+(System.currentTimeMillis() - lastTime) + "毫秒"); 52 | } 53 | }); 54 | } 55 | }).start(); 56 | } else if (id == R.id.buttonLoad) { 57 | lastTime = System.currentTimeMillis(); 58 | String area_strs=CacheLoaderManager.getInstance().loadString("area_strs"); 59 | area_strs=area_strs+"\n\n"+CacheLoaderManager.getInstance().loadString("area_strs1"); 60 | Toast.makeText(MainActivity.this, "加载数据用时:" + (System.currentTimeMillis() - lastTime) + "毫秒", Toast.LENGTH_SHORT).show(); 61 | textView.setText(area_strs); 62 | }else if(id==R.id.buttonClear){ 63 | CacheLoaderManager.getInstance().clear(); 64 | textView.setText(null); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Sample/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 16 | 17 | 21 |