Giter Site home page Giter Site logo

z-chu / rxcache Goto Github PK

View Code? Open in Web Editor NEW
392.0 9.0 37.0 4.52 MB

简单一步,缓存搞定。这是一个专用于 RxJava,解决 Android 中对任何 Observable 发出的结果做缓存处理的框架

License: Apache License 2.0

Java 96.94% Kotlin 3.06%
rxjava-android rxcache rxjava cache rxjava2

rxcache's Introduction

RxCache

Download

简单一步,缓存搞定。这是一个专用于 RxJava,解决 Android 中对任何 Observable 发出的结果做缓存处理的框架。

下载APK

特性

缓存层级

  • Observable
  • 内存缓存 - LruCache
  • 磁盘缓存 - DiskLruCache

目前已有的存储策略

  • 优先网络
  • 优先缓存
  • 优先缓存,并设置超时时间
  • 仅加载网络,但数据依然会被缓存
  • 先加载缓存,后加载网络
  • 仅加载网络,不缓存

Getting started

Add the dependencies

allprojects {
    repositories {     
       maven { url 'https://jitpack.io' }
    }
}

RxJava 2.0

implementation 'com.github.z-chu.RxCache:rxcache:2.3.5'

RxJava 3.0

implementation 'com.github.z-chu.RxCache:rxcache:3.0.0'

可添加 Kotlin 扩展,解决泛型擦除问题

implementation 'com.github.z-chu.RxCache:rxcache-kotlin:2.3.5'

首先创建一个 RxCache 实例

rxCache = new RxCache.Builder()
                .appVersion(1)//当版本号改变,缓存路径下存储的所有数据都会被清除掉
                .diskDir(new File(getCacheDir().getPath() + File.separator + "data-cache"))
                .diskConverter(new GsonDiskConverter())//支持Serializable、Json(GsonDiskConverter)
                .memoryMax(2*1024*1024)
                .diskMax(20*1024*1024)
                .build();

再使用 compose()操作符变换, 注意把<~>替换成你的数据类型

observable
	.compose(rxCache.<~>>transformObservable("custom_key", type, CacheStrategy.firstCache()))
	.subscribe(new Observer<CacheResult<~>>() {
		...
		@Override
		public void onNext(CacheResult<~> cacheResult) {
			Object data=cacheResult.getData();//获取你的数据
		}
		...
	}
	

Retrofit

在如果你使用的是 retrofit 那可原有代码的基础上,仅需2行代码搞定,一步到位!!!

Observable 调用

//注意在 <~> 中声明数据源的类型
.compose(rxCache.<~>transformObservablekey,type,CacheStrategy.firstCache()))
.map(new CacheResult.MapFunc<~>())

Flowable 调用

.compose(rxCache.<~>transformFlowablekey,type,CacheStrategy.firstCache()))
.map(new CacheResult.MapFunc<~>())

在这里声明缓存策略即可,不影响原有代码结构

如何你纠结 Key 值的取名,建议使用 ("方法名"+"参数名:"+"加参数值")

CacheStrategy

CacheStrategy 类中提供如下缓存策略:

策略选择 摘要
firstRemote() 优先网络
firstCache() 优先缓存
firstCacheTimeout(milliSecond) 优先缓存,并设置超时时间
onlyRemote() 仅加载网络,但数据依然会被缓存
onlyCache() 仅加载缓存
cacheAndRemote() 先加载缓存,后加载网络
none() 仅加载网络,不缓存

缓存的保存会在数据响应后用异步的方式保存,不会影响数据的响应时间。

如需要用同步方式保存,每个策略都有对应的同步保存方式 如: CacheStrategy.firstRemoteSync() 使用同步保存方式,数据会在缓存写入完以后才响应。

CacheResult

CacheResult 类,包含的属性如下:

public class CacheResult<T> {
    private ResultFrom from;//数据来源,原始observable、内存或硬盘
    private String key;
    private T data; // 数据
    private long timestamp; //数据写入到缓存时的时间戳,如果来自原始observable则为0
	...
}

Default rxCache

你也可以使用默认的 RxCache:
初始化默认的 RxCache

RxCache.initializeDefault(rxcache)

再这样使用

observable
	.compose(RxCache.getDefault().<~>>transformObservable("custom_key", type, strategy))
	...

如果不初始化默认的 RxCache,这样使用缓存会保存到 Environment.getDownloadCacheDirectory()
appVersion 会永远为 1

Kotlin

推荐使用 kotlin ,规避了泛型擦除,可不传 type, 无比简单 :

observable
	.rxCache("custom_key", strategy) //这样会使用默认的 RxCache ,你也可以传入任意 rxcache 使用
	.subscribe(object : Observer<CacheResult<~>>  {
		...
	}
	

泛型

因为泛型擦除的原因,遇到 List<~> 这样的泛型时可以这样使用:

// <~> 为List元素的数据类型
.compose(rxCache.<List<~>>transformer("custom_key", new TypeToken<List<~>>() {}.getType(), strategy))

没有泛型时 Type 直接传 Class 即可

.compose(rxCache.<Bean>transformer("custom_key",Bean.class, strategy))

如果你使用 Kotlin 则没有这个问题

.rxCache(rxcache,"custom_key", strategy)

基础用法

保存缓存:

如 保存字符串到内存和硬盘:

rxCache
	.save("test_key1","RxCache is simple", CacheTarget.MemoryAndDisk)
	.subscribeOn(Schedulers.io())
	.subscribe();

保存方式提供了 3 种选择:

public enum CacheTarget {
    Memory,
    Disk,
    MemoryAndDisk;
...
}

读取缓存:

读取的顺序会按照内存-->硬盘的顺序读取 如 读取缓存中的字符串:

 rxCache
	.<String>load("test_key1", String.class)
	.map(new CacheResult.MapFunc<String>())
	.subscribe(new Consumer<String>() {
		@Override
		public void accept(String value) throws Exception {
			
		}
	});

同步获取缓存:

 CacheResult<String> = rxCache.<String>loadSync("test_key1", String.class);

混淆配置

本 Library 不需求添加额外混淆配置,所以代码都可被混淆

rxcache's People

Contributors

nanbone avatar shiweibsw avatar z-chu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rxcache's Issues

关于分页缓存的管理

如果我缓存了分页的1-3页,我想调用第一页接口刷新,我怎么才能把2-3页的缓存数据给清除掉呢?

内存缓存会膨胀

LruMemoryCache内部存放大小以及插入时间的辅助Map,并不会在存实际数据的LruCache清除无效数据后进行清除,会无限制增长。

 private LruCache<String, Object> mCache;
    private HashMap<String, Integer> memorySizeMap;//储存初次加入缓存的size,规避对象在内存中大小变化造成的测量出错
    private HashMap<String, Long> timestampMap;

public <T> boolean save(String key, T value) {
        if (null != value) {
            memorySizeMap.put(key, (int) countSize(value));
            mCache.put(key, value);
            timestampMap.put(key, System.currentTimeMillis());
        }
        return true;
    }

解决办法:重写LruCache的entryRemoved方法,在这里分别对memorySizeMap和timestampMap进行移除对应的key

怎么更好的支持多用户的缓存呢?

如题,求教:app有多用户切换登录的情况,针对同一个url的请求,返回结果是不一样的,用这个lib怎么支持呢,是key值加上userId后缀,还是缓存针对不同用户用不同的目录呢?

报这个是什么错误额?

ClassNotFoundException: Didn't find class "androidx.collection.LruCache" on path: DexPathList[

在model 中加上相关的缓存代码

public class HomeNewRecommendModel implements HomeNewRecommendContract.Model {
@OverRide
public Observable getHomeNewRecommendData(String baby_id) {
return HomeIndexAPI.get().getHomeNewRecommendData(baby_id).compose(new DefaultTransformer<>()).compose(
RxCache.getDefault().transformObservable("my_home/v317" + baby_id,new TypeToken(){}.getType(),
CacheStrategy.firstCache())).map(new CacheResult.MapFunc());
}
}

缓存第二次获取不到

首次进入请求网络时,理论上缓存已经存在,但是每次重新调用,还是会走网络,但是将app杀死再次进入时则正常获取。
使用的缓存策略为优先缓存。
这是什么问题呢?

transformer 返回值

我用Rxjava用的是Flowable和consumer来做的,RxCache里面方法返回的ObservableTransformer用不了,有没有什么办法兼容一下,或者给个思路怎么来适配下

GsonDiskConverter 转换问题

当返回结果是一个List类型而不是普通的Object时,如果使用GsonDiskConverter转换,首次加载内存没有问题,但是退出应用后(后台也清除),再次冷启动,就会报错,ClassCastException: com.google.gson.internal.LinkedTreeMap, 初步确定是Gson解析泛型造成的,请问有好的修改建议解决这个问题吗?

缓存策略问题

ETag →0f47f5cd1b7dee9f

Access-Control-Allow-Origin →*
Cache-Control →no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Connection →keep-alive
Content-Type →application/json
Date →Wed, 30 May 2018 09:30:49 GMT
ETag →0f47f5cd1b7dee9f
Expires →Thu, 19 Nov 1981 08:52:00 GMT
Pragma →no-cache
Server →nginx
Transfer-Encoding →chunked

通过对ETag判断是否变化来更新

磁盘缓存无法删除问题

类RxCache/rxcache/src/main/java/com/zchu/rxcache/CacheCore.java

/**
     * 删除缓存
     */
    boolean remove(String key) {
        boolean isRemove = true;
        if (memory != null) {
            isRemove = memory.remove(key);
        }
        if (disk != null) {
            isRemove = isRemove && disk.remove(key);
        }
        return isRemove;
    }

isRemove = isRemove && disk.remove(key);这行代码在内存缓存不存在的时候会导致磁盘缓存无法被清理;
可修改为
isRemove = isRemove & disk.remove(key);

2.3.3的库引用失败

Unable to resolve dependency for ':app@chineseDebug/compileClasspath': Could not resolve com.github.z-chu.RxCache:rxcache:2.3.3.

是不是2.3.3 的版本 没有上传到jitpack
退到2.3.1 也不行。

原来使用的项目太旧,androidx 2.3.5的又用不了

【建议】【抛砖】希望加入 extension。

图长这样:
image

fun <T> Observable<T>.rcCache(name: String,
                              type: Type,
                              vararg conditions: Any
) = this.compose(RxCache.cache(name, type, *conditions))!!

fun <T> Observable<T>.rcLoad(name: String,
                             type: Type,
                             vararg conditions: Any
) = this.compose(RxCache.load(name, type, *conditions))!!

fun <T> Observable<T>.rcSave(name: String,
                             type: Type,
                             vararg conditions: Any
) = this.compose(RxCache.save(name, type, *conditions))!!

这么调用:

Uploading image.png…

LruDiskCache出现问题

02-28 15:36:31.346 29465-30386/com.prohua.dovedemo E/[RxCache]: LruDiskCache.save(LruDiskCache.java:70)
save: value=com.prohua.dovedemo.bean.NetBase@2a2de86 , status=true

你好我在使用中有些问题

当我使用cacheAndRemote作为缓存策略的时候 第一次进入没有问题,当我 关掉app 重新进入的时候 会导致崩溃 但是我看错误日志 也没有什么 比较像的exception
然后还有一个问题 就是firstCache这个策略 是优先缓存 然后会显示网络数据嘛? 就是 我设置这个以后 会优先显示 本地缓存 然后当我网络数据过来以后 还会显示网络数据吗?
最后还有一个问题 就是 cacheAndRemote这个策略是 先显示缓存 然后再显示网络数据 是嘛 当我关掉网络的时候 这个策略 是不是 还是显示不出来数据啊

使用缓存问题

RxCache 有没有设置此缓存,不会在超出设置的缓存大小时,而被清理掉?

RxCache 几种模式在移动端场景。

核心问题如题。
在我刚准备分析一下源码,我突然无法对作者提供部分缓存模式的应用场景进行描述。
也在网络上面进行搜索,对移动端有见解文章不多。如果作者有时间能否列举一下,让
使用者也用个明白。 感谢你的开源。

Jcenter 仓库地址已失效

Could not resolve all files for configuration ':tft:opsDebugRuntimeClasspath'.
Could not resolve com.zchu:rxcache:2.3.1.
Required by:
project :tft
> Could not resolve com.zchu:rxcache:2.3.1.
> Could not get resource 'https://dl.bintray.com/zchu/maven/com/zchu/rxcache/2.3.1/rxcache-2.3.1.pom'.
> Could not GET 'https://dl.bintray.com/zchu/maven/com/zchu/rxcache/2.3.1/rxcache-2.3.1.pom'. Received status code 403 from server: Forbidden

请上传至其他可用的仓库

为什么本地有缓存数据,但是没有网络的情况下,仍然加载不了缓存数据,而是报的网络异常错误,是哪里被拦截了吗?

``//这是配置
public Observable doNetSubscribe(Observable observable,
BehaviorSubject lifecycleSubject,
String cacheKey,
IObservableStrategy strategy
) {
return observable
.compose(RxThreadUtils.bindLife(lifecycleSubject))
.compose(rxCache.transformObservable(cacheKey, String.class, strategy))
.map(new Function<CacheResult, T>() {
@OverRide
public T apply(CacheResult tCacheResult) throws Exception {
Log.e("本地缓存数据:", tCacheResult.toString());
return tCacheResult.getData();
}
})
// .map(new CacheResult.MapFunc())
.compose(RxThreadUtils.handleResult())
.compose(RxThreadUtils.rxThreadHelper());
}
//这是网络请求
RxManager.getInstance().doNetSubscribe(dxyService.indexInfo(1, 7),
lifecycleSubject, "indexInfo", CacheStrategy.cacheAndRemote())
.subscribe(new RxNetSubscriber() {
@OverRide
protected void _onNext(String s) {
RxLogUtils.d("加载数据:" + s);
FirstPageBean bean = MyAPP.getGson().fromJson(s, FirstPageBean.class);
notifyData(bean);
}

                @Override
                protected void _onError(String error, int code) {
                    RxLogUtils.e("异常:" + error);
                    super._onError(error, code);
                    RxToast.normal(error);
                }
            });`

cacheAndRemote使用问题

CacheStrategy.cacheAndRemote()这个缓存策略在 存在缓存网络错误 时没有走onNext,只回调了一次onError,但是在Debug调试CacheAndRemoteStrategy中的代码时,正常返回,回调一次onError一次onNext,求问一下这是什么问题

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.