Rxjava初始

来源:互联网 发布:小米无人机 知乎 编辑:程序博客网 时间:2024/06/13 22:01

了解Rxjava


使用

当我们讲一个东西的时候必须是会使用,得从使用方面扯起

     Observable.create(new Observable.OnSubscribe<String>() {            @Override            public void call(Subscriber<? super String> subscriber) {                subscriber.onNext("333");            }        }).map(new Func1<String, Integer>() {            @Override            public Integer call(String s) {                return null;            }        }).subscribeOn(Schedulers.io())        .observeOn(AndroidSchedulers.mainThread())        .subscribe(new Subscriber<Integer>() {            @Override            public void onCompleted() {                result.setText("Completed");            }            @Override            public void onError(Throwable e) {                result.setText("Error");            }            @Override            public void onNext(Integer integer) {                result.setText(integer);            }        });

从这段代码我们可以得出这是一个流式API调用风格,有些人也叫链式。
这是RxJava第一个优势:让我们的代码看起来结构清晰,虽然代码可能更复杂了,但是对后期的维护,功能扩展,以及别人看代码的易读性提高了。
当然这个流式编程的好处不止这些,因为他之后和各种操作符以及和扩展的观察者模式有联系。

基础

  • 被观察者Observable
    • Observable决定什么时候触发事件以及触发怎样的事件
    • 常见的创建方式有三种,create,just,from,这里就不细讲了
  • 观察者Observer,Subscriber
    • Observer是一个接口,有三个方法onNext,onComplete,onError,
    • Subscriber是Observer的子类,扩展了一个onStart和unsubscribe方法

那么下来我们就结合这个代码来讲讲Rxjava

在网上随便一百度我们都可以搜到,Rxjava是扩展的观察者模式+异步编程
以及神奇的操作符

扩展的观察者模式

为什么说是扩展的观察者模式呢

  • 普通的观察者模式:

    1. 观察者订阅被观察者,比如读者和杂志,读者就是观察者,杂志就是被观察者,读者订阅杂志是符合逻辑的

    2. 普通观察者模式发起通知是通过update()

  • Rxjava的扩展的观察者模式是:

    1. 被观察者订阅观察者,也就是杂志订阅读者,有些人就感到很奇怪了。其实这是因为Rxjava是流式调用风格,这个的发起对象就是Observable,也就是被观察者。

    2. Rxajva的观察者发起通知除了onNext(等价于update)外,还多了几个方法,onComplete和onError

    那么这里虽然是被观察者(杂志)订阅观察者(读者),但是真实的逻辑依然是读者订阅了杂志,但是在表面上,我们让杂志“假装”订阅了读者,以便于保持流式API调用风格不变。

观察者模式的好处我们肯定都知道,是一种数据主动推送的形式,即Push,数据源更新了,我们可以主动通知界面更新。不使用观察者,数据都是主动获取的,即PULL方式

异步编程

异步是相对于主线程来讲的子线程操作,在这里我们不妨使用线程调度这个概念更加贴切。

图片

  • subscribeOn()它指示Observable在一个指定的调度器上创建(只作用于被观察者创建阶段)。只能指定一次,如果指定多次则以第一次为准
  • observeOn()指定在事件传递(加工变换)和最终被处理(观察者)的发生在哪一个调度器。可指定多次,每次指定完都在下一步生效。

说的通俗点,就是subscribeOn()指定了被观察者的创建是在哪一个线程上,但是指定多次以第一次为准而observeOn()则是指定下一步是在哪一线程进行的。

    public interface MovieService {    //String baseUrl = "https://api.douban.com/v2/movie/";    //https://api.douban.com/v2/movie/top250?start=0&count=10    @GET("top250")    retrofit2.Call<MovieEntity> getTopMovie(@Query("start")int start, @Query("count") int count);    @GET("top250")    rx.Observable<MovieEntity> getTopMovieByRxjava(@Query("start")int start, @Query("count")int count);    @GET("top250")    rx.Observable<HttpResult<List<Subject>>> getTopMovieByRxjava_T(@Query("start")int start, @Query("count")int count);}
        Retrofit retrofit = new Retrofit.Builder()                .baseUrl(HttpMethods.BASE_URL)                .addConverterFactory(GsonConverterFactory.create())                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())                .build();        MovieService movieService = retrofit.create(MovieService.class);        movieService.getTopMovieByRxjava(0, 10)               .subscribeOn(Schedulers.io())                .observeOn(AndroidSchedulers.mainThread())                .subscribe(new Subscriber<MovieEntity>() {                    @Override                    public void onCompleted() {                        Toast.makeText(MainActivity.this, "Get Top Movie Completed", Toast.LENGTH_SHORT).show();                    }                    @Override                    public void onError(Throwable e) {                        result_rx_TV.setText(e.getMessage());                    }                    @Override                    public void onNext(MovieEntity movieEntity) {                        result_rx_TV.setText(movieEntity.getTitle());                    }                });

这也是Rxjava的一个最佳体验吧,和Retrofit结合,我们可以看到我们在进行网络请求也就是得到了一个被观察者Observable,然后通过syvscribeOn(Schedulers.io())让其运行在io线程,当我们数据请求完毕后,就会主动调用观察者的onNext,onCompleted,onError方法更新UI.

从源码角度分析异步编程

就在上面我们分析了整个Rxjava的异步编程的一个过程

     Observable.create(new Observable.OnSubscribe<String>() {            @Override            public void call(Subscriber<? super String> subscriber) {                subscriber.onNext("333");            }        }).map(new Func1<String, Integer>() {            @Override            public Integer call(String s) {                return null;            }        }).subscribeOn(Schedulers.io())        .observeOn(AndroidSchedulers.mainThread())        .subscribe(new Subscriber<Integer>() {            @Override            public void onCompleted() {                result.setText("Completed");            }            @Override            public void onError(Throwable e) {                result.setText("Error");            }            @Override            public void onNext(Integer integer) {                result.setText(integer);            }        });

图片

  • 1. 首先我们create(Observable.OnSubscribe)的时候创建被观察者

        /**    * Invoked when Observable.subscribe is called.     */     public interface OnSubscribe<T> extends Action1<Subscriber<? super T>> {        // cover for generics insanity    }

    我们可以看到注释的汉语意思就是当被观察者Observable.subscribe被调用时调用,也就是调用call

        public interface Action1<T> extends Action {        void call(T t);    }

    而这里面实现的call方法的参数也就是Subscriber观察者,也就是我们在第一步订阅时传的参数

  • 2. 其次我们有一个Observable.subscribe(new Subscriber{})

    跟踪源码发现最终执行

        // assign to `observer` so we return the protected version    hook.onSubscribeStart(observable, observable.onSubscribe).call(subscriber);

    而这个onSubscribeStart就是Obervable.OnSubscribe类型,然后调用它的call方法,心细的人可能发现Observable.OnSubscribe就是create的时候new的那个,难道这个call就是那个自己实现的call吗,然而答案是否定的。此时还不是调用的我们create中的OnSubscribe的call方法,而是调用了一个lift方法,这个里面又new了一个Observable.OnSubscribe,也有一个call方法

        public final <R> Observable<R> lift(final Operator<? extends R, ? super T> operator) {    return new Observable<R>(new OnSubscribe<R>() {        @Override        public void call(Subscriber<? super R> o) {            try {                Subscriber<? super T> st = hook.onLift(operator).call(o);                try {                    // new Subscriber created and being subscribed with so 'onStart' it                    st.onStart();                    onSubscribe.call(st);                } catch (Throwable e) {                    // localized capture of errors rather than it skipping all operators                     // and ending up in the try/catch of the subscribe method which then                    // prevents onErrorResumeNext and other similar approaches to error handling                    Exceptions.throwIfFatal(e);                    st.onError(e);                }            } catch (Throwable e) {                Exceptions.throwIfFatal(e);                // if the lift function failed all we can do is pass the error to the final Subscriber                // as we don't have the operator available to us                o.onError(e);            }        }    });

    我们可以看到这个call方法中有st.Start(),这就是上面基础–onStart中讲的当被观察者和观察者建立关系后,在被观察者向观察者发送消息前调用的,进行一些初始化操作。

    初始化后然后调用OnSubscribe的call方法,这个也就是我们create的那个自定义call方法

    那么回过头来看第六行

    Subscriber<? super T> st = hook.onLift(operator).call(o);

    从第六行我们可以看到,他是把一个观察者作为参数传进去,返回值仍旧是观察者。

    我觉得这里应该是:

    a. lift是一个基础操作,我看其他merge,map等操作符都会调用这个,也就是它应该是为了保证它的流式调用,对观察者进行封装.

    b. 可能也是一种代理模式,将具体的操作交给一个新的代理观察者去发起通知,符合面向对象。

  • 3. 这下我们就可以在Observable中的OnSubscriber的call(Subscriber)中发起通知更新UI。
    但虽然表面上看起来是被观察者发起的通知,实际我们也看到了call(Subscriber),我们还是通过观察者来真正发起通知的。

  • 4. 发送事件就可以通过onNext,onComplete,onError。等价于观察者模式的update()


结束