├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── think │ │ └── cache │ │ └── samples │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ └── timg.jpg │ ├── java │ │ └── com │ │ │ └── think │ │ │ └── cache │ │ │ └── samples │ │ │ ├── ToastUtils.java │ │ │ ├── bitmap │ │ │ ├── BitmapActivity.java │ │ │ └── BitmapFragment.java │ │ │ ├── custom │ │ │ ├── CustomActivity.java │ │ │ └── CustomFragment.java │ │ │ ├── json │ │ │ ├── JsonActivity.java │ │ │ └── JsonFragment.java │ │ │ ├── main │ │ │ ├── MainActivity.java │ │ │ └── MainFragment.java │ │ │ └── string │ │ │ ├── StringActivity.java │ │ │ └── StringFragment.java │ └── res │ │ ├── layout │ │ ├── activity.xml │ │ ├── fragment_bitmap.xml │ │ ├── fragment_collection.xml │ │ ├── fragment_custom.xml │ │ ├── fragment_json.xml │ │ ├── fragment_main.xml │ │ └── fragment_string.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 │ └── think │ └── cache │ └── samples │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── think │ │ │ └── cache │ │ │ ├── BitmapByteMapper.java │ │ │ ├── ByteMapper.java │ │ │ ├── BytesMapper.java │ │ │ ├── Cache.java │ │ │ ├── CacheManager.java │ │ │ ├── DiskCacheManager.java │ │ │ ├── FileManager.java │ │ │ ├── MemoryCacheManager.java │ │ │ ├── Optional.java │ │ │ ├── SerializableByteMapper.java │ │ │ └── TCache.java │ └── res │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── think │ └── cache │ └── ExampleUnitTest.java ├── local.properties ├── png └── tcache.gif └── settings.gradle /README.md: -------------------------------------------------------------------------------- 1 | # TCache 2 | 3 | TCache是一个封装的Android缓存框架,使用具有很大的灵活性,下面将介绍该框架的使用方法和设计思想 4 | ![TCacheSamples](png/tcache.gif) 5 | 6 | ## TCache使用方法 7 | 8 | - 获得TCache对象,默认是存储在 **context.getCacheDir()** 的 **tcache** 目录下的. 9 | - 可以通过String类型的key缓存你想要缓存的数据,如Bitmap,JSONObject,String,byte[]等等. 10 | - 可以获得对应key缓存的数据是否过期 11 | - 可以清除指定key对应的缓存或清除所有缓存 12 | - 可以指定自定义的缓存目录,并管理缓存目录中文件的数量和缓存目录的空间. 13 | - 可以通过自定义的对象字节转换器,缓存你想缓存的对象数据,如Samples中缓存Intent 14 | 15 | ## TCache获取方法和接口介绍 16 | 17 | - 1.获取TCache 18 | ``` java 19 | //通过Context获取对象 20 | public static TCache get(Context context) 21 | //通过Context,并指定缓存的根目录 22 | public static TCache get(Context context, String rootCacheDir) 23 | //通过Context,并指定缓存的根目录,缓存的相对目录 24 | public static TCache get(Context context, String rootCacheDir, String relativeCacheDir) 25 | //通过Context,缓存的根目录,缓存的相对目录,存储目录最多文件数,最大缓存目录空间 26 | public static TCache get(Context context, String rootCacheDir, String relativeCacheDir, 27 | int maxDiskTotalCount, int maxDiskTotalSpace) 28 | //通过Context,缓存的根目录,缓存的相对目录,存储目录最多文件数,最大缓存目录空间,指定缓存默认失效时间 29 | public static TCache get(Context context, String rootCacheDir, String relativeCacheDir, 30 | int maxDiskTotalCount, int maxDiskTotalSpace, int defCacheAge) 31 | ``` 32 | 33 | - 2.TCache提供的缓存数据接口CacheManager,该接口标示这TCache提供了一些缓存数据和获取缓存的方法,如Bitmap,JSONObject等 34 | 35 | ``` java 36 | interface CacheManager extends Cache { 37 | //缓存字节数组 38 | void putBytes(String key, byte[] bytes); 39 | //获取缓存的字节数组 40 | byte[] getBytes(String key); 41 | //缓存Bitmap 42 | void putBitmap(String key, Bitmap bitmap); 43 | //获取缓存的Bitmap 44 | Bitmap getBitmap(String key); 45 | //缓存序列化对象 46 | void putSerializable(String key, T obj); 47 | //获取缓存的序列化对象 48 | T getSerializable(String key); 49 | //缓存JSONObject 50 | void putJSONObject(String key, JSONObject obj); 51 | //获取缓存的JSONObject 52 | JSONObject getJSONObject(String key) throws JSONException; 53 | } 54 | ``` 55 | 56 | - 3.CacheManager的父接口Cache,该接口标示了TCache提供的对象字节转换器来缓存任一对象,TCache判读指定缓存是否过期和清除操作 57 | 58 | ``` java 59 | interface Cache { 60 | //通过字节转换器缓存对象 61 | void putByteMapper(String key, T obj, ByteMapper mapper); 62 | //通过字节转换器获取缓存的对象 63 | T getByteMapper(String key, ByteMapper mapper); 64 | //通过默认的有效缓存周期判断指定的对象是否过期 65 | boolean isExpired(String key); 66 | //通过指定的的有效缓存周期判断指定的对象是否过期 67 | boolean isExpired(String key, long age); 68 | //清除指定的缓存 69 | void evict(String key); 70 | //清除所有缓存 71 | void evictAll(); 72 | //是否有指定key的缓存 73 | boolean isCached(String key); 74 | } 75 | ``` 76 | 77 | - 4.对象字节转换器接口ByteMapper,通过该接口可以完成任意对象和字节数组的相互转换 78 | 79 | ``` java 80 | public interface ByteMapper { 81 | //通过对象获取字节数组 82 | byte[] getBytes(T obj); 83 | //通过字节数组获取对象 84 | T getObject(byte[] bytes); 85 | } 86 | ``` 87 | 88 | - 5.TCache提供了几个默认的字节转换器,如bitmap等 89 | 90 | ``` java 91 | public class BitmapByteMapper implements ByteMapper { 92 | 93 | BitmapByteMapper() { 94 | 95 | } 96 | 97 | @Override 98 | public byte[] getBytes(Bitmap bitmap) { 99 | ByteArrayOutputStream bos = new ByteArrayOutputStream(); 100 | bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos); 101 | return bos.toByteArray(); 102 | } 103 | 104 | @Override 105 | public Bitmap getObject(byte[] bytes) { 106 | return BitmapFactory.decodeByteArray(bytes, 0, bytes.length); 107 | } 108 | } 109 | ``` 110 | 111 | ## TCache的设计思想 112 | 113 | - 缓存目录管理 114 | TCache采用分目录管理的方式管理不同位置的缓存,比如默认的tcache目录,tcache默认的缓存空间是50M,默认的缓存文件数量是500个,生命是不限的.TCache可以同时管理多个相对缓存目录,这些目录和tcache目录的性质是一样的. 115 | - 数据如何持久存储 116 | TCache会将指定key的数据用一个目录层文件的方式换出起来 117 | - 如何缓存任意数据 118 | 如何缓存任一数据,因为任何数据在计算机上都是以字节的形式存储的,因此TCache设计了字节对象转换器,这样用户就可以自己扩展自己想存储的数据了,比如Samples中的Intent对象. 119 | - 写文件 120 | TCache采用nio的方式进行读写文件,比寻常的io stream更高效. 121 | - 二级缓存 122 | 为了提高缓存的读取效率,设计了二级缓存,将暂时使用的缓存数据会缓存到内存中. 123 | - 缓存过期机制 124 | 如上所述,每个key对应的数据就是一个文件,那么这个数据文件的last modified time就是文件最后的缓存时间,TCache会修改该缓存文件对应父目录的last modified time时间,TCache会根据这个时间去判读是否过期,比如缓存了一个key为"xxx/yyy/zzz"的数据"ABCD",也可以获得key"xxx"的缓存是否过期,这样可以对相同类型的数据进行用户指定的缓存过期判断. 125 | - 缓存清除 126 | 同上的过期机制,缓存清除一个清除指定的目录或文件 127 | - 线程控制 128 | 因为缓存数据到disk上是通常的IO操作,所以TCache在put时对线程进行判断,防止在主线程进行Cache操作. 129 | 130 | ## TCache总结 131 | TCache是一个方便缓存数据的实用框架,便于扩展;但也有不足,欢迎大家提出[issues](https://github.com/borneywpf/TCache/issues)指正交流,不胜感激!!! 132 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.1" 6 | defaultConfig { 7 | applicationId "com.think.cache.samples" 8 | minSdkVersion 15 9 | targetSdkVersion 23 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile project(':library') 24 | compile fileTree(dir: 'libs', include: ['*.jar']) 25 | compile 'com.android.support:appcompat-v7:23.0.0' 26 | compile "com.android.support:design:23.0.0" 27 | compile "io.reactivex.rxjava2:rxjava:2.0.6" 28 | compile "io.reactivex.rxjava2:rxandroid:2.0.1" 29 | 30 | testCompile 'junit:junit:4.12' 31 | } 32 | -------------------------------------------------------------------------------- /app/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 /home/borney/data/opt/android-sdk-linux/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 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/think/cache/samples/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.think.cache.samples; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.think.cache.samples", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/assets/timg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/borneywpf/TCache/6c148af38ea19404063d689a8318a84971f949ab/app/src/main/assets/timg.jpg -------------------------------------------------------------------------------- /app/src/main/java/com/think/cache/samples/ToastUtils.java: -------------------------------------------------------------------------------- 1 | package com.think.cache.samples; 2 | 3 | import android.content.Context; 4 | import android.widget.Toast; 5 | 6 | /** 7 | * Created by borney on 3/6/17. 8 | */ 9 | 10 | public class ToastUtils { 11 | public static void toast(Context context, String msg) { 12 | Toast.makeText(context, msg, Toast.LENGTH_SHORT).show(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/think/cache/samples/bitmap/BitmapActivity.java: -------------------------------------------------------------------------------- 1 | package com.think.cache.samples.bitmap; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v4.app.FragmentTransaction; 6 | import android.support.v7.app.ActionBar; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.support.v7.widget.Toolbar; 9 | 10 | import com.think.cache.samples.R; 11 | 12 | /** 13 | * Created by borney on 3/6/17. 14 | */ 15 | 16 | public class BitmapActivity extends AppCompatActivity { 17 | @Override 18 | protected void onCreate(@Nullable Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | setContentView(R.layout.activity); 21 | 22 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 23 | setSupportActionBar(toolbar); 24 | ActionBar ab = getSupportActionBar(); 25 | ab.setDisplayHomeAsUpEnabled(false); 26 | 27 | BitmapFragment tasksFragment = 28 | (BitmapFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame); 29 | if (tasksFragment == null) { 30 | // Create the fragment 31 | tasksFragment = BitmapFragment.instance(); 32 | FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 33 | transaction.add(R.id.contentFrame, tasksFragment); 34 | transaction.commit(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/think/cache/samples/bitmap/BitmapFragment.java: -------------------------------------------------------------------------------- 1 | package com.think.cache.samples.bitmap; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.os.Bundle; 7 | import android.support.annotation.Nullable; 8 | import android.support.v4.app.Fragment; 9 | import android.util.Log; 10 | import android.view.LayoutInflater; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | import android.widget.EditText; 14 | import android.widget.ImageView; 15 | 16 | import com.think.cache.TCache; 17 | import com.think.cache.samples.R; 18 | import com.think.cache.samples.ToastUtils; 19 | 20 | import java.io.IOException; 21 | 22 | import io.reactivex.Observable; 23 | import io.reactivex.ObservableEmitter; 24 | import io.reactivex.ObservableOnSubscribe; 25 | import io.reactivex.android.schedulers.AndroidSchedulers; 26 | import io.reactivex.schedulers.Schedulers; 27 | 28 | /** 29 | * Created by borney on 3/6/17. 30 | */ 31 | 32 | public class BitmapFragment extends Fragment implements View.OnClickListener { 33 | private static final String TAG = "TCache"; 34 | private EditText mKey; 35 | private ImageView mCacheData; 36 | private TCache mTCache; 37 | 38 | public static BitmapFragment instance() { 39 | BitmapFragment fragment = new BitmapFragment(); 40 | return fragment; 41 | } 42 | 43 | @Override 44 | public void onAttach(Context context) { 45 | super.onAttach(context); 46 | mTCache = TCache.get(context); 47 | } 48 | 49 | @Nullable 50 | @Override 51 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, 52 | @Nullable Bundle savedInstanceState) { 53 | View v = inflater.inflate(R.layout.fragment_bitmap, container, false); 54 | mKey = (EditText) v.findViewById(R.id.key); 55 | v.findViewById(R.id.put).setOnClickListener(this); 56 | v.findViewById(R.id.get).setOnClickListener(this); 57 | mCacheData = (ImageView) v.findViewById(R.id.cachedata); 58 | v.findViewById(R.id.expired).setOnClickListener(this); 59 | v.findViewById(R.id.evict).setOnClickListener(this); 60 | return v; 61 | } 62 | 63 | @Override 64 | public void onClick(View v) { 65 | switch (v.getId()) { 66 | case R.id.put: 67 | put(); 68 | break; 69 | case R.id.get: 70 | get(); 71 | break; 72 | case R.id.expired: 73 | expired(); 74 | break; 75 | case R.id.evict: 76 | evict(); 77 | break; 78 | default: 79 | break; 80 | } 81 | 82 | } 83 | 84 | private void evict() { 85 | String key = mKey.getText().toString(); 86 | mTCache.evict(key); 87 | ToastUtils.toast(getContext(), "清除缓存:" + key); 88 | } 89 | 90 | private void expired() { 91 | String key = mKey.getText().toString(); 92 | ToastUtils.toast(getContext(), "Expired:" + mTCache.isExpired(key, 10)); 93 | } 94 | 95 | private void put() { 96 | Observable.create(new ObservableOnSubscribe() { 97 | @Override 98 | public void subscribe(ObservableEmitter e) throws Exception { 99 | try { 100 | String key = mKey.getText().toString(); 101 | Bitmap bitmap = BitmapFactory.decodeStream(getContext().getAssets().open("timg.jpg")); 102 | mTCache.putBitmap(key, bitmap); 103 | e.onComplete(); 104 | } catch (IOException ex) { 105 | ex.printStackTrace(); 106 | } 107 | } 108 | }).subscribeOn(Schedulers.io()) 109 | .observeOn(AndroidSchedulers.mainThread()) 110 | .subscribe(); 111 | } 112 | 113 | private void get() { 114 | String key = mKey.getText().toString(); 115 | Bitmap cacheData = mTCache.getBitmap(key); 116 | mCacheData.setImageBitmap(cacheData); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /app/src/main/java/com/think/cache/samples/custom/CustomActivity.java: -------------------------------------------------------------------------------- 1 | package com.think.cache.samples.custom; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v4.app.FragmentTransaction; 6 | import android.support.v7.app.ActionBar; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.support.v7.widget.Toolbar; 9 | 10 | import com.think.cache.samples.R; 11 | 12 | /** 13 | * Created by borney on 3/6/17. 14 | */ 15 | 16 | public class CustomActivity extends AppCompatActivity { 17 | @Override 18 | protected void onCreate(@Nullable Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | setContentView(R.layout.activity); 21 | 22 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 23 | setSupportActionBar(toolbar); 24 | ActionBar ab = getSupportActionBar(); 25 | ab.setDisplayHomeAsUpEnabled(false); 26 | 27 | CustomFragment tasksFragment = 28 | (CustomFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame); 29 | if (tasksFragment == null) { 30 | // Create the fragment 31 | tasksFragment = CustomFragment.instance(); 32 | FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 33 | transaction.add(R.id.contentFrame, tasksFragment); 34 | transaction.commit(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/think/cache/samples/custom/CustomFragment.java: -------------------------------------------------------------------------------- 1 | package com.think.cache.samples.custom; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.support.annotation.Nullable; 7 | import android.support.v4.app.Fragment; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.EditText; 12 | import android.widget.TextView; 13 | 14 | import com.think.cache.ByteMapper; 15 | import com.think.cache.TCache; 16 | import com.think.cache.samples.R; 17 | import com.think.cache.samples.ToastUtils; 18 | import com.think.cache.samples.main.MainActivity; 19 | 20 | import java.net.URISyntaxException; 21 | 22 | import io.reactivex.Observable; 23 | import io.reactivex.ObservableEmitter; 24 | import io.reactivex.ObservableOnSubscribe; 25 | import io.reactivex.android.schedulers.AndroidSchedulers; 26 | import io.reactivex.schedulers.Schedulers; 27 | 28 | /** 29 | * Created by borney on 3/6/17. 30 | */ 31 | 32 | public class CustomFragment extends Fragment implements View.OnClickListener { 33 | private EditText mKey; 34 | private TextView mCacheData; 35 | private TCache mTCache; 36 | 37 | public static CustomFragment instance() { 38 | CustomFragment fragment = new CustomFragment(); 39 | return fragment; 40 | } 41 | 42 | @Nullable 43 | @Override 44 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, 45 | @Nullable Bundle savedInstanceState) { 46 | View view = inflater.inflate(R.layout.fragment_custom, container, false); 47 | view.findViewById(R.id.put).setOnClickListener(this); 48 | view.findViewById(R.id.get).setOnClickListener(this); 49 | view.findViewById(R.id.expired).setOnClickListener(this); 50 | view.findViewById(R.id.evict).setOnClickListener(this); 51 | mKey = (EditText) view.findViewById(R.id.key); 52 | mCacheData = (TextView) view.findViewById(R.id.cachedata); 53 | return view; 54 | } 55 | 56 | @Override 57 | public void onAttach(Context context) { 58 | super.onAttach(context); 59 | mTCache = TCache.get(context, "custom"); 60 | } 61 | 62 | @Override 63 | public void onClick(View v) { 64 | switch (v.getId()) { 65 | case R.id.put: 66 | put(); 67 | break; 68 | case R.id.get: 69 | get(); 70 | break; 71 | case R.id.expired: 72 | expired(); 73 | break; 74 | case R.id.evict: 75 | evict(); 76 | break; 77 | default: 78 | break; 79 | } 80 | } 81 | 82 | private void evict() { 83 | String key = mKey.getText().toString(); 84 | mTCache.evict(key); 85 | ToastUtils.toast(getContext(), "清除缓存:" + key); 86 | } 87 | 88 | private void expired() { 89 | String key = mKey.getText().toString(); 90 | ToastUtils.toast(getContext(), "Expired:" + mTCache.isExpired(key, 10)); 91 | } 92 | 93 | private void put() { 94 | Observable.create(new ObservableOnSubscribe() { 95 | @Override 96 | public void subscribe(ObservableEmitter e) throws Exception { 97 | Intent intent = new Intent(getContext(), MainActivity.class); 98 | String key = mKey.getText().toString(); 99 | mTCache.putByteMapper(key, intent, new IntentByteMapper()); 100 | e.onComplete(); 101 | } 102 | }).subscribeOn(Schedulers.io()) 103 | .observeOn(AndroidSchedulers.mainThread()) 104 | .subscribe(); 105 | } 106 | 107 | private void get() { 108 | String key = mKey.getText().toString(); 109 | Intent intent = mTCache.getByteMapper(key, new IntentByteMapper()); 110 | mCacheData.setText(intent.toUri(0)); 111 | } 112 | 113 | class IntentByteMapper implements ByteMapper { 114 | 115 | @Override 116 | public byte[] getBytes(Intent obj) { 117 | String uri = obj.toUri(0); 118 | return uri.getBytes(); 119 | } 120 | 121 | @Override 122 | public Intent getObject(byte[] bytes) { 123 | String uri = new String(bytes); 124 | try { 125 | return Intent.parseUri(uri, 0); 126 | } catch (URISyntaxException e) { 127 | e.printStackTrace(); 128 | } 129 | return null; 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /app/src/main/java/com/think/cache/samples/json/JsonActivity.java: -------------------------------------------------------------------------------- 1 | package com.think.cache.samples.json; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v4.app.FragmentTransaction; 6 | import android.support.v7.app.ActionBar; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.support.v7.widget.Toolbar; 9 | 10 | import com.think.cache.samples.R; 11 | 12 | /** 13 | * Created by borney on 3/6/17. 14 | */ 15 | 16 | public class JsonActivity extends AppCompatActivity { 17 | @Override 18 | protected void onCreate(@Nullable Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | setContentView(R.layout.activity); 21 | 22 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 23 | setSupportActionBar(toolbar); 24 | ActionBar ab = getSupportActionBar(); 25 | ab.setDisplayHomeAsUpEnabled(false); 26 | 27 | JsonFragment tasksFragment = 28 | (JsonFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame); 29 | if (tasksFragment == null) { 30 | // Create the fragment 31 | tasksFragment = JsonFragment.instance(); 32 | FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 33 | transaction.add(R.id.contentFrame, tasksFragment); 34 | transaction.commit(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/think/cache/samples/json/JsonFragment.java: -------------------------------------------------------------------------------- 1 | package com.think.cache.samples.json; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.EditText; 11 | import android.widget.TextView; 12 | 13 | import com.think.cache.TCache; 14 | import com.think.cache.samples.R; 15 | import com.think.cache.samples.ToastUtils; 16 | 17 | import org.json.JSONArray; 18 | import org.json.JSONException; 19 | import org.json.JSONObject; 20 | 21 | import io.reactivex.Observable; 22 | import io.reactivex.ObservableEmitter; 23 | import io.reactivex.ObservableOnSubscribe; 24 | import io.reactivex.android.schedulers.AndroidSchedulers; 25 | import io.reactivex.schedulers.Schedulers; 26 | 27 | /** 28 | * Created by borney on 3/6/17. 29 | */ 30 | 31 | public class JsonFragment extends Fragment implements View.OnClickListener { 32 | private static final String TAG = "TCache"; 33 | private EditText mKey; 34 | private TextView mCacheData; 35 | private TCache mTCache; 36 | private JSONObject mPutObject; 37 | 38 | public static JsonFragment instance() { 39 | JsonFragment fragment = new JsonFragment(); 40 | return fragment; 41 | } 42 | 43 | @Override 44 | public void onAttach(Context context) { 45 | super.onAttach(context); 46 | mTCache = TCache.get(context); 47 | } 48 | 49 | @Nullable 50 | @Override 51 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, 52 | @Nullable Bundle savedInstanceState) { 53 | View v = inflater.inflate(R.layout.fragment_json, container, false); 54 | mKey = (EditText) v.findViewById(R.id.key); 55 | TextView data = (TextView) v.findViewById(R.id.data); 56 | mPutObject = getJsonObject(); 57 | data.setText(mPutObject.toString()); 58 | v.findViewById(R.id.put).setOnClickListener(this); 59 | v.findViewById(R.id.get).setOnClickListener(this); 60 | mCacheData = (TextView) v.findViewById(R.id.cachedata); 61 | v.findViewById(R.id.expired).setOnClickListener(this); 62 | v.findViewById(R.id.evict).setOnClickListener(this); 63 | return v; 64 | } 65 | 66 | private JSONObject getJsonObject() { 67 | JSONObject jo = new JSONObject(); 68 | try { 69 | jo.put("name", "json"); 70 | JSONArray ja = new JSONArray(); 71 | ja.put(0, new Person("Json1", 11)); 72 | ja.put(1, new Person("Json2", 22)); 73 | jo.put("array", ja); 74 | } catch (JSONException e) { 75 | e.printStackTrace(); 76 | } 77 | return jo; 78 | } 79 | 80 | @Override 81 | public void onClick(View v) { 82 | switch (v.getId()) { 83 | case R.id.put: 84 | put(); 85 | break; 86 | case R.id.get: 87 | get(); 88 | break; 89 | case R.id.expired: 90 | expired(); 91 | break; 92 | case R.id.evict: 93 | evict(); 94 | break; 95 | default: 96 | break; 97 | } 98 | 99 | } 100 | 101 | private void evict() { 102 | String key = mKey.getText().toString(); 103 | mTCache.evict(key); 104 | ToastUtils.toast(getContext(), "清除缓存:" + key); 105 | } 106 | 107 | private void expired() { 108 | String key = mKey.getText().toString(); 109 | ToastUtils.toast(getContext(), "Expired:" + mTCache.isExpired(key, 10)); 110 | } 111 | 112 | private void put() { 113 | Observable.create(new ObservableOnSubscribe() { 114 | @Override 115 | public void subscribe(ObservableEmitter e) throws Exception { 116 | String key = mKey.getText().toString(); 117 | mTCache.putJSONObject(key, mPutObject); 118 | e.onComplete(); 119 | } 120 | }).subscribeOn(Schedulers.io()) 121 | .observeOn(AndroidSchedulers.mainThread()) 122 | .subscribe(); 123 | } 124 | 125 | private void get() { 126 | String key = mKey.getText().toString(); 127 | try { 128 | JSONObject cacheData = mTCache.getJSONObject(key); 129 | mCacheData.setText(cacheData.toString()); 130 | } catch (JSONException e) { 131 | e.printStackTrace(); 132 | } 133 | } 134 | 135 | private class Person { 136 | private int age; 137 | private String name; 138 | 139 | Person(String name, int age) { 140 | this.name = name; 141 | this.age = age; 142 | } 143 | 144 | public int getAge() { 145 | return age; 146 | } 147 | 148 | public void setAge(int age) { 149 | this.age = age; 150 | } 151 | 152 | public String getName() { 153 | return name; 154 | } 155 | 156 | public void setName(String name) { 157 | this.name = name; 158 | } 159 | 160 | @Override 161 | public String toString() { 162 | return "Person{" + 163 | "age=" + age + 164 | ", name='" + name + '\'' + 165 | '}'; 166 | } 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /app/src/main/java/com/think/cache/samples/main/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.think.cache.samples.main; 2 | 3 | import android.os.Bundle; 4 | import android.support.v4.app.FragmentTransaction; 5 | import android.support.v7.app.ActionBar; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.support.v7.widget.Toolbar; 8 | 9 | import com.think.cache.samples.R; 10 | 11 | public class MainActivity extends AppCompatActivity { 12 | 13 | @Override 14 | protected void onCreate(Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | setContentView(R.layout.activity); 17 | 18 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 19 | setSupportActionBar(toolbar); 20 | ActionBar ab = getSupportActionBar(); 21 | ab.setDisplayHomeAsUpEnabled(false); 22 | 23 | MainFragment tasksFragment = 24 | (MainFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame); 25 | if (tasksFragment == null) { 26 | // Create the fragment 27 | tasksFragment = MainFragment.instance(); 28 | FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 29 | transaction.add(R.id.contentFrame, tasksFragment); 30 | transaction.commit(); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/think/cache/samples/main/MainFragment.java: -------------------------------------------------------------------------------- 1 | package com.think.cache.samples.main; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.support.annotation.Nullable; 7 | import android.support.v4.app.Fragment; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | 12 | import com.think.cache.samples.R; 13 | import com.think.cache.samples.custom.CustomActivity; 14 | import com.think.cache.samples.json.JsonActivity; 15 | import com.think.cache.samples.bitmap.BitmapActivity; 16 | import com.think.cache.samples.string.StringActivity; 17 | 18 | /** 19 | * Created by borney on 3/6/17. 20 | */ 21 | 22 | public class MainFragment extends Fragment implements View.OnClickListener { 23 | 24 | public static MainFragment instance() { 25 | MainFragment fragment = new MainFragment(); 26 | return fragment; 27 | } 28 | 29 | @Nullable 30 | @Override 31 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, 32 | @Nullable Bundle savedInstanceState) { 33 | View view = inflater.inflate(R.layout.fragment_main, container, false); 34 | view.findViewById(R.id.string).setOnClickListener(this); 35 | view.findViewById(R.id.json).setOnClickListener(this); 36 | view.findViewById(R.id.other).setOnClickListener(this); 37 | view.findViewById(R.id.custom).setOnClickListener(this); 38 | return view; 39 | } 40 | 41 | @Override 42 | public void onClick(View v) { 43 | Context context = getContext(); 44 | switch (v.getId()) { 45 | case R.id.string: 46 | context.startActivity(new Intent(context, StringActivity.class)); 47 | break; 48 | case R.id.json: 49 | context.startActivity(new Intent(context, JsonActivity.class)); 50 | break; 51 | case R.id.other: 52 | context.startActivity(new Intent(context, BitmapActivity.class)); 53 | break; 54 | case R.id.custom: 55 | context.startActivity(new Intent(context, CustomActivity.class)); 56 | break; 57 | default: 58 | break; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/think/cache/samples/string/StringActivity.java: -------------------------------------------------------------------------------- 1 | package com.think.cache.samples.string; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v4.app.FragmentTransaction; 6 | import android.support.v7.app.ActionBar; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.support.v7.widget.Toolbar; 9 | 10 | import com.think.cache.samples.R; 11 | 12 | /** 13 | * Created by borney on 3/6/17. 14 | */ 15 | 16 | public class StringActivity extends AppCompatActivity { 17 | @Override 18 | protected void onCreate(@Nullable Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | setContentView(R.layout.activity); 21 | 22 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 23 | setSupportActionBar(toolbar); 24 | ActionBar ab = getSupportActionBar(); 25 | ab.setDisplayHomeAsUpEnabled(false); 26 | 27 | StringFragment tasksFragment = 28 | (StringFragment) getSupportFragmentManager().findFragmentById(R.id.contentFrame); 29 | if (tasksFragment == null) { 30 | // Create the fragment 31 | tasksFragment = StringFragment.instance(); 32 | FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 33 | transaction.add(R.id.contentFrame, tasksFragment); 34 | transaction.commit(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/think/cache/samples/string/StringFragment.java: -------------------------------------------------------------------------------- 1 | package com.think.cache.samples.string; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.EditText; 11 | import android.widget.TextView; 12 | 13 | import com.think.cache.TCache; 14 | import com.think.cache.samples.R; 15 | import com.think.cache.samples.ToastUtils; 16 | 17 | import io.reactivex.Observable; 18 | import io.reactivex.ObservableEmitter; 19 | import io.reactivex.ObservableOnSubscribe; 20 | import io.reactivex.android.schedulers.AndroidSchedulers; 21 | import io.reactivex.schedulers.Schedulers; 22 | 23 | /** 24 | * Created by borney on 3/6/17. 25 | */ 26 | 27 | public class StringFragment extends Fragment implements View.OnClickListener { 28 | private EditText mKey; 29 | private EditText mData; 30 | private TextView mCacheData; 31 | 32 | private TCache mTCache; 33 | 34 | public static StringFragment instance() { 35 | StringFragment fragment = new StringFragment(); 36 | return fragment; 37 | } 38 | 39 | @Override 40 | public void onAttach(Context context) { 41 | super.onAttach(context); 42 | mTCache = TCache.get(context); 43 | } 44 | 45 | @Nullable 46 | @Override 47 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, 48 | @Nullable Bundle savedInstanceState) { 49 | View v = inflater.inflate(R.layout.fragment_string, container, false); 50 | mKey = (EditText) v.findViewById(R.id.key); 51 | mData = (EditText) v.findViewById(R.id.data); 52 | v.findViewById(R.id.put).setOnClickListener(this); 53 | v.findViewById(R.id.get).setOnClickListener(this); 54 | mCacheData = (TextView) v.findViewById(R.id.cachedata); 55 | v.findViewById(R.id.iscached).setOnClickListener(this); 56 | v.findViewById(R.id.expired).setOnClickListener(this); 57 | v.findViewById(R.id.evict).setOnClickListener(this); 58 | return v; 59 | } 60 | 61 | @Override 62 | public void onClick(View v) { 63 | switch (v.getId()) { 64 | case R.id.put: 65 | put(); 66 | break; 67 | case R.id.get: 68 | get(); 69 | break; 70 | case R.id.iscached: 71 | isCached(); 72 | break; 73 | case R.id.expired: 74 | expired(); 75 | break; 76 | case R.id.evict: 77 | evict(); 78 | break; 79 | default: 80 | break; 81 | } 82 | 83 | } 84 | 85 | private void isCached() { 86 | String key = mKey.getText().toString(); 87 | ToastUtils.toast(getContext(), "是否缓存:" + key + ":" + mTCache.isCached(key)); 88 | } 89 | 90 | private void evict() { 91 | String key = mKey.getText().toString(); 92 | mTCache.evict(key); 93 | ToastUtils.toast(getContext(), "清除缓存:" + key); 94 | } 95 | 96 | private void expired() { 97 | String key = mKey.getText().toString(); 98 | ToastUtils.toast(getContext(), "Expired:" + mTCache.isExpired(key, 10)); 99 | } 100 | 101 | private void put() { 102 | Observable.create(new ObservableOnSubscribe() { 103 | @Override 104 | public void subscribe(ObservableEmitter e) throws Exception { 105 | String key = mKey.getText().toString(); 106 | String data = mData.getText().toString(); 107 | mTCache.putSerializable(key, data); 108 | e.onComplete(); 109 | } 110 | }).subscribeOn(Schedulers.io()) 111 | .observeOn(AndroidSchedulers.mainThread()) 112 | .subscribe(); 113 | } 114 | 115 | private void get() { 116 | String key = mKey.getText().toString(); 117 | String cacheData = mTCache.getSerializable(key); 118 | mCacheData.setText(cacheData); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 13 | 14 | 20 | 21 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_bitmap.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 14 | 21 | 22 |