使用RxJava自己构造一个三级缓存的实例

通常我们说的三级缓存是指Memory,Disk,NetWork,因为我们都知道从网络读取一条数据往往存在各种因素速度不尽人意,如果一个应用中任何数据都是实时从网络获取,那么我们想象一下用户每次都要面对如进度条转个两三圈才显示数据这种体验肯定是不佳的,所以我们需要缓存数据,所以本文介绍使用RxJava通过实例来讲解如何缓存数据。

定义一个数据实体类,简单的定义了一个数据内容,以及一个时间用来代表缓存时长。

public class CacheData {

    private static final int CACHE_TIME = 5000; 

    public String data;
    public long time;

    public CacheData(String value) {
        this.data = value;
        time = System.currentTimeMillis();
    }

    public boolean isUpToData() {
        return System.currentTimeMillis() - time >= CACHE_TIME;
    }
}

定义Memory,Disk,NetWork三个缓存的Observable:

public class Source {

    /**
     * 内存缓存
     */
    CacheData memery;
    /**
     * 硬盘缓存
     */
    CacheData disk;
    /**
     * 网络获取数据
     */
    int requestData;

    public Source() {
        Timber.tag("Source");
    }

    /**
     * 从内存里读取缓存
     */
    public Observable<CacheData> getFromMemory() {
        Observable<CacheData> observable = Observable.create(new Observable.OnSubscribe<CacheData>() {
            @Override
            public void call(Subscriber<? super CacheData> subscriber) {
                subscriber.onNext(memery);
                subscriber.onCompleted();
            }
        });
        return observable.compose(getFrom("MEMORY"));
    }

    /**
     * 从硬盘中读取缓存
     */
    public Observable<CacheData> getFromDisk() {
        Observable<CacheData> observable = Observable.create(new Observable.OnSubscribe<CacheData>() {
            @Override
            public void call(Subscriber<? super CacheData> subscriber) {
                subscriber.onNext(disk);
                subscriber.onCompleted();
            }
        });
        return observable.compose(getFrom("DISK"));
    }

    /**
     * 从网络中读取数据
     */
    public Observable<CacheData> getFromNet() {
        Observable<CacheData> observable = Observable.create(new Observable.OnSubscribe<CacheData>() {
            @Override
            public void call(Subscriber<? super CacheData> subscriber) {
                requestData ++;
                subscriber.onNext(new CacheData("Data is = " + requestData));
                subscriber.onCompleted();
            }
        });
        return observable.doOnNext(new Action1<CacheData>() {
            @Override
            public void call(CacheData cacheData) {
                memery = cacheData;
                disk = cacheData;
            }
        }).compose(getFrom("NETWORK"));
    }

    /**
     * Transformer转换  判断数据的状态
     */
    private Observable.Transformer<CacheData, CacheData> getFrom( final String source) {
        Observable.Transformer<CacheData, CacheData> loadFromTransformer = new Observable.Transformer<CacheData, CacheData>() {
            @Override
            public Observable<CacheData> call(Observable<CacheData> cacheDataObservable) {
                return cacheDataObservable.doOnNext(new Action1<CacheData>() {
                    @Override
                    public void call(CacheData cacheData) {
                        if (cacheData == null) {
                            Timber.e(source + " --- cacheData is null check again ---");
                        } else if (cacheData.isUpToData()) {
                            Timber.e(source + " --- cacheData is out of time ---");
                        } else {
                            Timber.e(source + " --- cacheData you gotta ---");
                        }
                    }
                });
            }
        };
        return loadFromTransformer;
    }
}

代码中我们分别定义了memory、disk缓存并且我们定义了一个requestData用来假设是网络数据。其中的memory和disk的Observable比较好理解就是发射对应的缓存就好,我们主要讲里面一些涉及的操作符。

doOnNext:标示当Observable在调用onNext发射数据的时候会调用到这里面,然后我们可以通过自定义一个Action把里面的数据缓存到memory和disk中去。

observable.doOnNext(new Action1<CacheData>() {
            @Override
            public void call(CacheData cacheData) {
                memery = cacheData;
                disk = cacheData;
            }
        })

Observable.Transformer:转换操作可以将源Observable通过不断他链式的结构能直接作用于Observable上去,常见于复用操作符等操作,这里我们通过使用它来打印数据是从哪里取出来的。

        Observable.Transformer<CacheData, CacheData> loadFromTransformer = new Observable.Transformer<CacheData, CacheData>() {
            @Override
            public Observable<CacheData> call(Observable<CacheData> cacheDataObservable) {
                return cacheDataObservable.doOnNext(new Action1<CacheData>() {
                    @Override
                    public void call(CacheData cacheData) {
                        if (cacheData == null) {
                            Timber.e(source + " --- cacheData is null check again ---");
                        } else if (cacheData.isUpToData()) {
                            Timber.e(source + " --- cacheData is out of time ---");
                        } else {
                            Timber.e(source + " --- cacheData you gotta ---");
                        }
                    }
                });
            }
        };

Ok,万事都准备好了 那么我们调用起来看看效果喽。

        Source source = new Source();
        observable = Observable.concat(source.getFromMemory(), source.getFromDisk(), source.getFromNet())
                .first(new Func1<CacheData, Boolean>() {
                    @Override
                    public Boolean call(CacheData cacheData) {
                        return null != cacheData && !cacheData.isUpToData();
                    }
                });

这里又涉及了两个操作符
concat:保证顺序的组合操作,这样一次从memory、disk、network中去数据。
first:取Observable中的第一个数据,我们这里自己定义了一个Func函数标示说取满足条件的第一个数据。

解释完了,我们使用subscribe订阅这个Observable:

      observable.subscribe(new Action1() {
            @Override
            public void call(Object o) {
                Timber.i("Result = " + ((CacheData) o).data);
            }
        });

最后我们看看效果。

MEMORY --- cacheData is null check again ---
DISK --- cacheData is null check again ---
NETWORK --- cacheData you gotta ---
I/MainActivity: Result = Data is = 1

MEMORY --- cacheData you gotta ---
I/MainActivity: Result = Data is = 1

我们可以看出第一次调用的时候 数据来自网络,第二次调用就来自内存了,符合我们的三级缓存的效果。

Thanks:http://blog.chinaunix.net/uid-20771867-id-5145681.html

demo地址:https://github.com/Neacy/BlogCode

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值