Android 使用RxJava+Retrofit +Realm 组合加载数据 <读取缓存 显示 请求网络数据 缓存最新数据 更新界面>(二)
来源:互联网 发布:淘宝店铺流量突然下降 编辑:程序博客网 时间:2024/05/02 00:39
继续完善上次懵懵懂懂的流程.
原理还是一样的.不明白的看一看
Android 使用RxJava+Retrofit +Realm 组合加载数据 <读取缓存 显示 请求网络数据 缓存最新数据 更新界面>(一)
这次整合的是数据库Realm点击查看中文文档感兴趣的可以去看看.
使用Realm的原因是它和Retrofit一样.天生支持Rxjava,当然还有其他的,不过我没用过.
Realm配置 Applaction中 ,如果配置了多进程的话.最好是判断一下包名,防止调用多次
private void initRealm() { RealmConfiguration realmConfiguration = new RealmConfiguration.Builder(this) .name("xxx.realm") .schemaVersion(1) .rxFactory(new RealmObservableFactory()) //默认Rxjava支持,貌似不写也可以 .deleteRealmIfMigrationNeeded()//测试使用,每次都删除原来的数据// .encryptionKey(key)// .modules(new MySchemaModule())// .migration(migration) .build(); Realm.setDefaultConfiguration(realmConfiguration); }
Realm 配合Rxjava查询方法,官方文档配置
// Combining Realm, Retrofit and RxJava (Using Retrolambda syntax for brevity)// Load all persons and merge them with their latest stats from GitHub (if they have any)Realm realm = Realm.getDefaultInstance();GitHubService api = retrofit.create(GitHubService.class);realm.where(Person.class).isNotNull("username").findAllAsync().asObservable() .filter(persons.isLoaded) .flatMap(persons -> Observable.from(persons)) .flatMap(person -> api.user(person.getGithubUserName()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(user -> showUser(user));
请注意异步查询不会阻塞当前线程,如上代码会立即返回一个 RealmResults 实例。如果你想确定该 RealmResults 已经加载完成请使用 filter operator 和 RealmResults.isLoaded() 方法。通过判断 RealmResults 是否已经加载可以得知查询是否已经完成。
以上为官网文档的原话,不过根据我实际上使用来说.使用Realm.getDefaultInstance().asObservable()会永远不掉用onComplete()方法,这是一个坑,还挺深的,而且使用过程中,多次调用onNext(),这样就会导致在Subscriber.onNext()多次调用,也就是说,界面将会被刷新多次
如果想取一次数据,需要使用 filter/first()
查询代码
final Realm realm = Realm.getDefaultInstance(); Observable<RecommendHome> dataSourceFromDb = realm.where(RecommendHome.class).findFirstAsync() .<RecommendHome>asObservable() .filter(new Func1<RecommendHome, Boolean>() { @Override public Boolean call(RecommendHome recommendHome) { LogUtils.w(TAG, "dataSource from realm"); return recommendHome.isLoaded(); } }) .first() .doOnCompleted(new Action0() { @Override public void call() { if (realm == null && !realm.isClosed()) { realm.close(); } } });
需要说明的是Realm有线程保护机制,不能多线程访问同一实例,它只能使用在创建他的线程中,根据官网文档说明异步查询不会阻塞当前线程,我也就相信了,也就是说 Rxjava 中很便捷的切换线程在这里就然并卵了
将查询和网络请求结合,这里我用到的还是之前提到的 concat 大体的意思就是将多个Observable发射的数据同到一个Subscriber中处理. 基于这个原理.修改 NetManager
类是同一个只是修改了其中的方法
public void getRecommendDataSource(Subscriber<RecommendHome> subscriber, boolean isConnection) { final Realm realm = Realm.getDefaultInstance(); Observable<RecommendHome> dataSourceFromDb = realm.where(RecommendHome.class).findFirstAsync() .<RecommendHome>asObservable() .filter(new Func1<RecommendHome, Boolean>() { @Override public Boolean call(RecommendHome recommendHome) { LogUtils.w(TAG, "dataSource from realm"); return recommendHome.isLoaded(); } }) .first() .doOnCompleted(new Action0() { @Override public void call() { if (realm == null && !realm.isClosed()) { realm.close(); } } }); Observable<RecommendHome> dataSourceFromNet = RetrofitManager.getWebApiService() .getRecommendHomeDatas() .doOnNext(new Action1<RecommendHome>() { @Override public void call(RecommendHome recommendHome) { LogUtils.w(TAG, "save to db"); Realm realm = Realm.getDefaultInstance(); realm.beginTransaction(); realm.copyToRealmOrUpdate(recommendHome); realm.commitTransaction(); realm.close(); } }) .subscribeOn(Schedulers.io()) .unsubscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); if (isConnection) { Observable.concat(dataSourceFromDb, dataSourceFromNet).subscribe(subscriber); } else { dataSourceFromDb.subscribe(subscriber); } }
调用的时候直接在Activity/Fragment 中传入Subscriber<T>
就可以了,这里的boolean参数是判断网络连接状态的,可有可无
Log如下
无网络状态
07-22 16:11:29.496 16479-16479: dataSource from realm07-22 16:11:29.746 16479-16479: dataSource from realm07-22 16:11:29.746 16479-16479: subscriber onNext07-22 16:11:29.766 16479-16479: subscriber onCompleted
有网络状态
07-22 16:13:13.246 16479-16479: dataSource from realm07-22 16:13:13.246 16479-16479: dataSource from realm07-22 16:13:13.246 16479-16479: subscriber onNext07-22 16:13:13.746 16479-19234: save to db07-22 16:13:13.826 16479-16479: subscriber onNext07-22 16:13:13.836 16479-16479: subscriber onCompleted
到这基本上就完成 读取数据 -> 显示 -> 请求网络数据 -> 缓存新数据 ->更新界面
就这样
—end
- Android 使用RxJava+Retrofit +Realm 组合加载数据 <读取缓存 显示 请求网络数据 缓存最新数据 更新界面>(二)
- Android 使用RxJava+Retrofit +Realm 组合加载数据 <读取缓存 显示 请求网络数据 缓存最新数据 更新界面>(一)
- Retrofit网络请求+GreenDao数据缓存
- Retrofit缓存网络数据RxCache--RxJava和数据库
- Retrofit+RxJava+Fresco图片加载框 请求网络数据
- 网络请求数据缓存
- Rxjava+Retrofit 请求数据
- 使用MVP+Retrofit+RxJava 图片加载使用Fresco 做网络请求并展示数据
- Android MVP框架+RxJava+Retrofit+cecycleView,请求网络数据并加载
- MVP+Rxjava+Retrofit+Fresco网络请求数据
- MVP框架使用Retrofit+Rxjava请求网络数据
- Android数据缓存加载,listview显示
- Android网络请求缓存,本地数据缓存流程图
- Android中网络请求数据以及其他数据本地缓存
- android轻量级缓存框架ASimpleCache的使用 (网络请求数据并缓存)
- android轻量级缓存框架ASimpleCache的使用 (网络请求数据并缓存)
- 使用缓存优化数据请求
- 简单的MVP+Retrofit+RxJava请求网络数据(一)
- iOS学习之iOS沙盒(sandbox)机制和文件操作
- 《Java源码分析》:HashSet
- hdu 5734 Acperience(2016 Multi-University Training Contest 2——化简公式,数学推导)
- POJ3641-Pseudoprime numbers
- ReentrantLock还是synchronized?
- Android 使用RxJava+Retrofit +Realm 组合加载数据 <读取缓存 显示 请求网络数据 缓存最新数据 更新界面>(二)
- 一个千万量级的APP使用的一些第三方库
- 使用无符号右移-&-栈 实现 十进制转十六进制
- nginx配置
- 站在巨人的肩膀上学习
- poj1062 昂贵的聘礼 (最短路)
- python去掉字符串中空格的方法
- 数字特征值-week3-C语言习题集
- TAIGA 部署