如题解决方案直接从中间开始读起,上面都是废话
Rxjava 最近很流行,我也跟上潮流开始学习这个… 这个很牛逼的流式编程
什么 异步, 观察者模式, 响应式变成. 方法连 Observable Observer Subscribe 事件
OMG 各种概念.各种的各种..都是什么鬼..看的头都大了.目前还处于混乱期.
只明白了一点.这东西Rxjava上手确实不是那么容易的,各种参考资料,文档 各种的各种.
给 Android 开发者的 RxJava 详解
ReactiveX/RxJava文档中文版
RxJava适用场景小结
深入浅出RxJava(一:基础篇)
深入浅出RxJava ( 二:操作符 )
深入浅出RxJava ( 三–响应式的好处 )
深入浅出RxJava ( 四-在Android中使用响应式编程 )
github 上一些相关的资源
Awesome-RxJava 大部分的资料我是也是在这里找到的
RxJava 官方的开源地址
RxAndroid android平台相关
RxPermissions Rx配套的 6.0的权限申请
RxBinding JakeWharton大神的 控件绑定的一些支持库 什么防抖动之类的
RxLifecycle 防止内存泄漏的
….更多的请自行google寻找. 梯子Host 请低调使用
上面的资料,我居然都看了一边,有些不只一遍…可是还是懵懵懂懂. 感谢这些资料的总结者,给我这种小白提供入门的机会.虽然我资质有限,还没入门.
但是通过这几天的摸索.多少还是理解了一些.虽然有限.比如: 简化逻辑.不需要在写一堆异步回调的接口.便捷的线程切换等一些简单的概念.开始的时候,简单的集成到项目中,还是很顺利的,因为不久前就把项目中的网络模块替换成了Retrofit + okHttp.所以集成Rxjava需要添加一些相关的依赖就可以了
compile ‘com.squareup.retrofit2:adapter-rxjava:2.1.0’
compile ‘com.tbruyelle.rxpermissions:rxpermissions:0.7.0@aar’ //不是必须 6.0以上的权限申请
compile ‘io.reactivex:rxandroid:1.2.1’
compile ‘io.reactivex:rxjava:1.1.6’
WebApiServices 接口改造
public interface WebApiServices {
@POST("/chaiche/api/recommend/home/")
Observable getRecommendHomeDatas();//把call 换成Observable 就可以了
}
Activity调用
RetrofitManager.getWebApiService()
.getRecommendHomeDatas()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1() {
@Override
public void call(RecommendHome recommendHome) {
setAdapter(recommendHome);
}
});
完成后部署测试,没crash 说明没问题.
对比Retrofit Call + CallBack形式的
Call call = RetrofitManager.getWebApiService().getRecommendHome();
call.enqueue(new Callback() {
@Override
public void onResponse(Call call, Response response) {
if (response.isSuccessful()) {
RecommendHome recommend = response.body();
setAdapter(recommend);
}else{
//TODO
}
}
@Override
public void onFailure(Call call, Throwable t) {
ToastManager.showShort(getActivity(),R.string.net_error);
}
});
好吧 .我承认.代码量确实没变化多少.可是,有没有感觉有那么一点点清晰?说白了就是好看了很多?有木有?
进一步的改进 创建NetManager ,封装请求管理.把网络请求方法和Activity/Fragment解耦,这样做的好处就是如果想替换网络请求框架了 不需要在动Activity/Fragment中调用网络请求的代码了
public class NetManager {
//在访问HttpMethods时创建单例
//这个单利据说是利用一个什么类加载器的原理.貌似这个,是线程安全的.感兴趣的话自行百度一下
private static class SingletonHolder {
private static final NetManager INSTANCE = new NetManager();
}
//获取单例
@org.jetbrains.annotations.Contract(pure = true)
public static NetManager getInstance() {
return SingletonHolder.INSTANCE;
}
public void getRecommendDataSource(Subscriber subscriber) {
RetrofitManager.getWebApiService()
.getRecommendHomeDatas()
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber);
}
}
调用 这里需要强调一下 不能使用一个Subscriber 否者第二次调用绝对不会得到返回值. 不信你可以试试
private Subscriber subscriber;
private void requestHomeData() {
subscriber = new Subscriber() {
@Override
public void onCompleted() {
LogUtils.w(TAG, "subscriber onCompleted");
}
@Override
public void onError(Throwable e) {
LogUtils.w(TAG, "subscriber onError");
ToastManager.showShort(getActivity(),R.string.net_error);
}
@Override
public void onNext(RecommendHome recommendHome) {
LogUtils.w(TAG, "subscriber onNext");
if (recommendHome == null) {
mListView.setEmptyView(img_noData);
} else {
setAdapter(recommendHome);
}
}
};
NetManager.getInstance().getRecommendDataSource(subscriber);
}
@Override
public void onDestroy() {
super.onDestroy();
if (subscriber.isUnsubscribed()) { //不知道有没有用..反正我是先加上了
subscriber.unsubscribe();
}
}
说道这里.其实这些只是初步的集成 调用. 如果想知道如题所说,以上都是废话
这样的过程
读取缓存 显示 请求网络数据 缓存最新数据 更新界面
我想做到的就是这么个过程,各种百度 google 文档等 能让我看懂理解的不多…不多 资质啊资质, 蛋蛋的忧伤飘过…….
找到的是使用
concat 操作符 说白了 就是把2个或者多个Observable连起来,按顺序执行,反正我是这么理解的
实现过程参考从零开始的Android新项目5 - Repository层(上) Retrofit、Repository组装 感谢博主提供的思想
代码如下 PS : 根据资料参考,写的demo .目的是总结一下实现过程. Copy 直接可在Activity/Fragment调用
private void test_15() {
final Observable fromDb = Observable.create(
new Observable.OnSubscribe() {
@Override
public void call(Subscriber super String> subscriber) {
String s = queryFormDb();
if (!s.equals("")) {
// System.out.println("fromDb onNext");
subscriber.onNext(s);
}
subscriber.onCompleted();
}
})
.map(new Func1() {
@Override
public String call(String s) {
// System.out.println("fromDb map call");
Logger.w(s);
return s;
}
})
.subscribeOn(Schedulers.io());
// .filter(new Func1() {
// @Override
// public Boolean call(String s) {
// return s.equals("");
// }
// });
final Observable fromNet = Observable.create(
new Observable.OnSubscribe() {
@Override
public void call(Subscriber super String> subscriber) {
String s = requestFromNet();
if (!s.equals("")) {
// System.out.println("fromNet onNext");
subscriber.onNext(s);
}
subscriber.onCompleted();
}
})
.map(new Func1() {
@Override
public String call(String s) {
// System.out.println("fromNet map call");
return s;
}
})
.doOnNext(new Action1() {
@Override
public void call(String s) {
if (!s.equals("")) {
// System.out.println("fromNet doOnNext call");
// System.out.println(s + "存入数据库");
Logger.w(s + "存入数据库");
}
}
})
.subscribeOn(Schedulers.io());
Observable.concat(fromDb, fromNet)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1() {
@Override
public void call(String s) {
System.out.println(s);
Logger.w(s);
}
},
new Action1() {
@Override
public void call(Throwable throwable) {
System.out.println(throwable.toString());
System.out.println(throwable.toString());
}
});
}
public String queryFormDb() {
return "来自数据库的数据";
}
public String requestFromNet() {
try {
Thread.sleep(2000); //模拟网络请求耗时操作 延时2秒
} catch (InterruptedException e) {
e.printStackTrace();
}
return "来自网络的数据";
}
Log如下
╔══════════════════════════════════════════════════════════ W/PRETTYLOGGER: ║ Thread: RxIoScheduler-2
W/PRETTYLOGGER: ║ (LaunchActivity.java:93)
W/PRETTYLOGGER: ║ LaunchActivity$1.call
W/PRETTYLOGGER: ║ 来自数据库的数据
╚══════════════════════════════════════════════════════════
╔══════════════════════════════════════════════════════════
W/PRETTYLOGGER: ║ Thread: main
W/PRETTYLOGGER: ║ LaunchActivity$6.call (LaunchActivity.java:141)
W/PRETTYLOGGER: ║ LaunchActivity$6.call (LaunchActivity.java:145)
W/PRETTYLOGGER: ║ 显示来自数据库的数据
╚══════════════════════════════════════════════════════════
╔══════════════════════════════════════════════════════════
W/PRETTYLOGGER: ║ Thread: RxIoScheduler-2
W/PRETTYLOGGER: ║ LaunchActivity$3.call (LaunchActivity.java:128)
W/PRETTYLOGGER: ║ LaunchActivity$3.call (LaunchActivity.java:134)
W/PRETTYLOGGER: ║ 来自网络的数据存入数据库
╚══════════════════════════════════════════════════════════
╔══════════════════════════════════════════════════════════ W/PRETTYLOGGER: ║ Thread: main
W/PRETTYLOGGER: ║ LaunchActivity$6.call (LaunchActivity.java:141)
W/PRETTYLOGGER: ║ LaunchActivity$6.call (LaunchActivity.java:145)
W/PRETTYLOGGER: ║ 显示来自网络的数据
╚══════════════════════════════════════════════════════════
另一种实现方式使用Rx同步并缓存网络数据
通过关联PublishSubject, 在插入数据完成后, 调用绑定观察者, 更新页面.
即.concatWith(mPublishSubject)和mPublishSubject.onNext(repos).
鉴于我还处于懵懵懂懂的状态.原谅我没太看明白.总结到这.我要把我上面贴出来的方法应用到我的项目中了.祝我成功
再次感谢以上总结资料的各位大神.
文笔有限,如有问题欢迎指正.如果你有更好的实现方法,欢迎留言交流,不过不要用Retrolambda 风格的.虽然简化,不过不适合学习中的我…