转载请注意:http://blog.csdn.net/wjzj000/article/details/54314319
本菜开源的一个自己写的Demo,希望能给Androider们有所帮助,水平有限,见谅见谅…
https://github.com/zhiaixinyang/PersonalCollect (拆解GitHub上的优秀框架于一体,全部拆离不含任何额外的库导入)
https://github.com/zhiaixinyang/MyFirstApp(Retrofit+RxJava+MVP)
这是一个系列博客,主线是梳理我在学习Retrofit,RxJava以及MVP中的遇到的坑以及从一点不懂到瞎几把啥也不懂的过程…
系列之一Retrofit链接:
http://blog.csdn.net/wjzj000/article/details/54287823
本系列RxJava的上部分:
http://blog.csdn.net/wjzj000/article/details/54312035
填补上篇遗留的坑
进入观察者模式
让我们回忆一下上篇文章中的那个demo:
Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
}})
.subscribe(new Observer<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
}
});
首先我们记住一点,这里是被观察者观察观察者;被订阅者订阅订阅者…虽然很反人类,但是为了更好的设置以及流式调用的体验,因此无伤大雅。
我们首先由Observable.create去创建了一个被观察者:
public static <T> Observable<T> create(OnSubscribe<T> f) {
return new Observable<T>(hook.onCreate(f));
}
public <T> OnSubscribe<T> onCreate(OnSubscribe<T> f) {
return f;
}
protected Observable(OnSubscribe<T> f) {
this.onSubscribe = f;
}
然后我们重写了call方法。这个方法最终来自于Action1。
我们获取一个被观察者之后,调用了subscribe(翻译:订阅)。这一步我们就开始订阅观察者了:
public final Subscription subscribe(final Observer<? super T> observer) {
if (observer instanceof Subscriber) {
return subscribe((Subscriber<? super T>)observer);
}
return subscribe(new ObserverSubscriber<T>(observer));
}
很明显这里我们需要传递一个传递一个观察者。因此我们demo中我们new了一个Observer。当然new一个Subscriber也一样…
这里重点来捋一捋传Action1的这种情况。上篇文章提到,Action1并没有直接或间接的继承或实现Observer相关的类或者接口。因此subscribe订阅方法势必有重载:
public final Subscription subscribe(final Action1<? super T> onNext) {
if (onNext == null) {
throw new IllegalArgumentException("onNext can not be null");
}
Action1<Throwable> onError = InternalObservableUtils.ERROR_NOT_IMPLEMENTED;
Action0 onCompleted = Actions.empty();
return subscribe(new ActionSubscriber<T>(onNext, onError, onCompleted));
}
这里我们可以看到,它其实还是调用了上边的那个重载方法。ActionSubscriber本质还是一个观察者:
public final class ActionSubscriber<T> extends Subscriber<T> {
final Action1<? super T> onNext;
final Action1<Throwable> onError;
final Action0 onCompleted;
public ActionSubscriber(Action1<? super T> onNext, Action1<Throwable> onError, Action0 onCompleted) {
this.onNext = onNext;
this.onError = onError;
this.onCompleted = onCompleted;
}
@Override
public void onNext(T t) {
onNext.call(t);
}
@Override
public void onError(Throwable e) {
onError.call(e);
}
@Override
public void onCompleted() {
onCompleted.call();
}
}
这里我们可以发现我们代替Observer(观察者),传递Action的时候是只能传Action1的,因此Aciton0是不行的。
再流程上梳理一遍这个过程:
被观察者创建一个被观察者对象,重写call,在call中调用观察者回调的引用,然后通过引用调用观察者的对应的onNext()等…
- Observable.create->call()->subscriber.onNext(…)
通过注册方法传递观察者,然后重写对应方法,拿到被观察者在call中传递的参数,完成自己的业务。
- .subscribe->onNext(…)等
情况就是这么个情况,说白了被观察者和观测者绑定在一起,然后通过重写特定的方法完成及时的回调。
尼玛,这有什么用?你逗我呢…
稍安勿躁,这些都是前戏。着啥急,皇上可一点不着急….
异步
接下来让我们直接上例子,来感受一下被RxJava支配的恐惧吧。
Demo_1:
用最原始的方式请求服务器的一张图片并且显示。
private String imgPaht="http://www.ohonor.xyz/image/TestImage.png";
Observable.create(new Observable.OnSubscribe<Bitmap>() {
@Override
public void call(Subscriber<? super Bitmap> subscriber) {
HttpURLConnection conn=null;
InputStream is=null;
Bitmap bitmap=null;
try {
URL url=new URL(imgPaht);
conn= (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setRequestMethod("GET");
if (conn.getResponseCode()==200){
is=conn.getInputStream();
bitmap= BitmapFactory.decodeStream(is);
subscriber.onNext(bitmap);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Bitmap>() {
@Override
public void call(Bitmap bitmap) {
ivImage.setImageBitmap(bitmap);
}
});
- 效果很简单,就是一张图。
这里我们在call之中进行网络访问,获取完图片的Bitmap之后调用了onNext(),然后在观察者中的onNext里直接用ImageView进行设置Bitmap。
重点来了!这里我们并没有new线程,Handler,AscyTask等等异步操作。
仅仅使用了俩句话就完成了这个过程:
//说白了就是被观察者在后台线程执行,也可以直接subscribeOn(Schedulers.newThread())
.subscribeOn(Schedulers.io())
//说白了就是观察者在主线程运行。(来自RxAndroid中的类)
.observeOn(AndroidSchedulers.mainThread())
如果我们不设置这俩个属性,那么而这会在默认的线程中执行。
接下来走一波RxJava+Retrofit
Demo_2:
例子就是本系列Retrofit的例子,不过是和RxJava进行了整合。
第一步改造Retrofit接口:
public interface RetrofitApi {
String URL = "http://www.ohonor.xyz/";
@GET("retrofit")
Observable<List<RetrofitBean>> getRetrofitDatasByRxJava();
}
在这里就是把之前返回值的Call改为了Observable,泛型依旧是我们需要的类型。也就是说直接返回一个被观察者。
//一切简单的初始化
datas= new ArrayList<>();
adapter=new RetrofitAdapter(this,datas);
rlvMain.setLayoutManager(new LinearLayoutManager(this));
rlvMain.setAdapter(adapter);
//初始化结束
Retrofit retrofit=new Retrofit.Builder()
.baseUrl(RetrofitApi.URL)
.addConverterFactory(GsonConverterFactory.create())
//这句话必不可少...因此我们需要额外依赖一个库
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
retrofit.create(RetrofitApi.class).getRetrofitDatasByRxJava()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<List<RetrofitBean>>() {
@Override
public void call(List<RetrofitBean> list) {
datas.addAll(list);
adapter.notifyDataSetChanged();
}
});
额外的依赖库
//版本号对应Retrofit的版本号即可
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
- 效果
这里我们为什么没有直接在Demo_2中模拟Demo_1…因为感觉Retrofit做下载感觉有点麻烦。个人认为Retrofit请求Json数据极为方便,尤其是和RxJava。
上述便是最好的证明。短短几行即完成了我们正常的网络请求。并且当我们在项目之中使用MVP设计框架后我们更能感受到项目的逻辑极为的清晰。
接下来捋一捋转化这么的功能,第一次接触可能感觉有些鸡肋,不过当我们在特定的情形之下。我们便能够感受这不可思议的强大。
转换
首先我们先构想一种场景:
当我们在写一个方法时,这个方法时继承的。至于它什么时候被调用我们并不清楚。我们只知道这个一个服务器图片链接。我们需要在当前的ImageView中把它显示出来。
那么此时我们可以用到转换这么一个功能….
(举的例子可能并不恰当,主要是引出转换这个概念)
Demo
@Override
public void downloadBitmap(String imagePath) {
//此处我们需要用到just方法
Observable.just(imagePath)
//然后使用map,重写call,获取到到相关内容后返回出去
.map(new Func1<String, Bitmap>() {
@Override
public Bitmap call(String s) {
HttpURLConnection conn=null;
InputStream is=null;
Bitmap bitmap=null;
try {
URL url=new URL(imgPaht);
conn= (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setRequestMethod("GET");
if (conn.getResponseCode()==200){
is=conn.getInputStream();
bitmap=BitmapFactory.decodeStream(is);
return bitmap;
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Bitmap>() {
@Override
public void call(Bitmap bitmap) {
ivImage.setImageBitmap(bitmap);
}
});
}
这里和我们正常使用的不同在于:
1,我们使用just方法来创建被观察者。
public static <T> Observable<T> just(final T value) {
return ScalarSynchronousObservable.create(value);
}
2,我们使用map方法进行转换,在map之中new一个Funct1传入俩个泛型分别是我们想从什么类型转到什么类型。
public final <R> Observable<R> map(Func1<? super T, ? extends R> func) {
return lift(new OperatorMap<T, R>(func));
}
//我们可以看到内容调用的是lift方法
public final <R> Observable<R> lift(final Operator<? extends R, ? super T> operator) {
return new Observable<R>(new OnSubscribeLift<T, R>(onSubscribe, operator));
}
class OnSubscribeLift<T, R> implements OnSubscribe<R>
如果在追下去就略微的有点复杂,所以到此就打住了。关于转换在这里仅仅是起一个头,如果业务需要就可以深入的去了解一发。
PS:相关源码基本都存放于我的这个开源项目之中:
https://github.com/zhiaixinyang/PersonalCollect
尾声
关于RxJava就暂时记录这么多,如果各位看官仍有疑惑,可以异步到大神们的专业博客上:
http://gank.io/post/560e15be2dca930e00da1083
最后希望各位看官可以star我的GitHub,三叩九拜,满地打滚求star:
https://github.com/zhiaixinyang/PersonalCollect
https://github.com/zhiaixinyang/MyFirstApp