RxJava 初探(网络请求)

RxJava 介绍


写在前面

rxjava 也用了好多次了。时隔多年,才终于有勇气挖一下它的源码。
这次主要研究了发布订阅流程 subscribe() 以及核心变换 lift(),至于其他的像线程切换 Schedulers、丰富的操作符啊,都有待研究。
之后可能会再更新几篇,也可能就太监了。。。
1.RxJava 源码分析之 —— lift 变换


What is RxJava?

RxJava 的思想是响应式编程,这是一种事件驱动的编程模式。事件驱动很熟悉吧,经典如通过 Listener 来监听点击事件再回调 OnClick(),这种方式早就烂大街了吧。RxJava 本质上与这种监听器没有区别,那么它又有什么独到之处呢?


Why RxJava?

它的独到之处在与它响应式的编程思想——一切皆抽象为事件。如果说对于点击事件,Android 本身已经提供了一套监听方案,那么网络请求呢,文件读写呢,还有数不清的事件呢。。此前,我们都是自己编写网络请求框架,然后对外提供回调接口 OnSuccess() 、OnFail()。换成文件读写,又得重新搞一套框架,我们累了,需要一个通用的解决方案,它就是 RxJava 。
By the way,解决了”回调地狱”只是顺带的好处罢了。


Where RxJava?

那么什么场景下使用它呢?
它的应用场合很多,本文将以网络请求为例做一个 Demo。

更多场景请参考这篇文章:
可能是东半球最全的RxJava使用场景小结


How RxJava?

要使用 RxJava 还得深入到代码层面。
它是基于观察者模式实现的,那么自然会有一个被观察者(可观察的对象) Observable 和 一个观察者(订阅者)Subscriber。


需要的第三方包

// app/build.gradle
dependencies {
    // 。。。

    // rxjava
    compile 'io.reactivex:rxjava:1.0.14'
    compile 'io.reactivex:rxandroid:1.1.0'

    // rxlifecycle
    compile 'com.trello:rxlifecycle:0.4.0'
    compile 'com.trello:rxlifecycle-components:0.4.0'
    // 上面4个包是必要的

    // okhttp
    compile 'com.squareup.okhttp:okhttp:2.7.2'

    // butterknife 
    compile 'com.jakewharton:butterknife:7.0.1'
}

最好配合上 retrolambda 这个插件,用 lambda 语法写起来才爽。

概念介绍

先来看一下 Subscriber 包含了哪些东西

// 打开源码我们看到 Subsctiber 实现了 Observer
public abstract class Subscriber<T> implements Observer<T>, Subscription { ... }

// 而 Observer 包含有一些回调函数
// {OnNext(), OnError(), OnComplete()}
public interface Observer<T> {
    void onNext(T t);
    void onError(Throwable e);
    void onCompleted();
}

然后看看它怎么订阅事件

// Subscriber 作为监听器,需要注册到 Observable 中:
// (我们才能在 Observable 中回调它的一些函数)
mObservable.subscribe(mSubscriber);

// 这类似于我们注册点击事件的监听:
mView.setOnClickListener(mOnClickListener);

// 可以对应起来理解,View 即是被观察者,
// 而 OnClickListener 则是订阅者。

其中,mSubscriber 是这样的

// 当然,正如 mOnClickListener 实现了 OnClick(),
// mSubscriber 作为匿名类实现了三个接口函数,像这样:
Subscriber mSubscriber = new Subscriber() {  
    @Override  
    public void onNext(String s) { }  

    @Override  
    public void onCompleted() { }  

    @Override  
    public void onError(Throwable e) { }  
};  

一些简化写法:

// 考虑到这样的匿名类写法比较冗长,而且不能用 lambda 简化,
// 作者还提供了 subscribe(mSubscriber) 的一些重载版本:
mObservable.subscribe(onNext);
mObservable.subscribe(onNext, onError);
mObservable.subscribe(onNext, onError, onComplete);
// 太棒了,它们都是函数式接口,可以用 lambda 简化代码。


再来看一下 Observable , 之前说到它可以被 Subcriber 订阅。但是在此之前,我们需要先创建它。

// 创建 Observable 实例
mObservable.create(mOnSubscribe); 

// 其中 mOnSubscribe 接口,用来制定事件分发的流程。
// 即按照一定顺序,回调之前注册好的三个函数: 
// {OnNext(), OnError(), OnComplete()}
Observable.OnSubscribe mOnSubscribe = new Observable.OnSubscribe() {
    @Override
    public void call(Subscribersuper String> subscriber) {
        String data = getData(); // 获取数据: 网络任务或是别的...
        if(data == null){ // 获取失败
            subscriber.onError(new Throwable("data 为空"));
            subscriber.onCompleted();
        }else{ // 获取成功
            subscriber.onNext(data);
            subscriber.onCompleted();
        }
    }
};

What’s more,Observable 还可以分别指定 Observable 和 Subcriber 的线程:

Observable.create(subscriber -> {})
    .subscribeOn(Schedulers.io()) // 指定 Observable 的线程 ———— 主线程。
    .observeOn(AndroidSchedulers.mainThread()); // 指定 Subscriber 的线程 ———— io 线程。

框架内部估计封装了线程切换的功能,这在 Android 的多线程环境中,极大地简化了线程操作。

实践

我们来试一下网络请求吧,从网上拉取一段字符串(http://publicobject.com/helloworld.txt)。首先,我们把一个请求看作一个事件,先创建一个事件对应的被观察者 NetworkObserable.getInstance() : Observable< String >。

public class NetworkObserable{
    ...
    // 获取一个 Observable 实例
    public static Observable getInstance() {
        return Observable.create((Observable.OnSubscribe)
                subscriber -> subscribeData(subscriber, NetworkHelper.getData(NetworkHelper.GET))
                // getData()发起一个GET请求,返回 String 数据。
            ).subscribeOn(Schedulers.io());  
            // 被观察的对象在 io 线程进行网络请求,也可以自己新开一个线程
    }

    // 取得网络数据后,回调 subscriber 的一些函数,在界面上显示这些数据
    private static void subscribeData(Subscribersuper String> subscriber, String data){
        if(data == null){
            subscriber.onError(new Throwable("data 为空"));
            subscriber.onCompleted();
        }else{
            subscriber.onNext(data);
            subscriber.onCompleted();
        }
    }
}

在点击按钮的时候订阅这个事件。

@OnClick(R.id.btn_GET) public void onClick() {
    NetworkObservable.getInstance()                 // 获取 Observable 实例
        .compose(this.bindToLifecycle())    // Rxlifecycle, 绑定到 Activity 的生命周期。
        .observeOn(AndroidSchedulers.mainThread())  // 指定观察者的线程————主线程。
        .subscribe(                                 // 订阅事件
            // onNext, 请求成功
            data -> mTvResult.setText(data),
            // onError, 请求失败
            throwable -> Toast.makeText(this, throwable.getMessage(), Toast.LENGTH_SHORT).show()
        );
}

然后,没有然后了。。。


附录

按照惯例,放上 Demo 地址,有兴趣可以下载一下:
https://github.com/fashare2015/my_rxjava_demo

你可能感兴趣的:(rxjava,响应式,rxjava)