Android从零开搞系列:网络框架系列(5)Retrofit+RxJava+MVP(中-下)RxJava篇(下)

转载请注意: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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值