Rxjava2源码分析四

Rxjava2源码分析三

这一篇主要是分享一下自定义操作符和几个常见的操作符。

自定义操作符的意义:在我看来学习自定义操作符的过程就是个检验你对Rxjava理解的过程。

下面我们来看一下Rxjava的简单使用场景,Rxjava+retrofit+okhttp

//定义接口api,这两个wangAndroid找的,感谢鸿洋大佬,随便看下就好,下面会分析使用。

public interface WangAndroidApi {
    //总数据
    @GET("project/tree/json")
    Observable<ProjectBean> getProject();

    //item数据
    @GET("project/list/{pageIndex}/json")
    Observable<ProjectItem> getProjectItem(@Path("pageIndex") int pageIndex, @Query("cid") int cid);
}

接下来我们需要两个javaBean,这里我就不占用篇幅展示了,给个截图。转换javaBean的工具或者方法大家随便百度搜索一下就有。


定义我们的网络工具类

public class HttpUtil {
    public final static String BASE_URL = "https://www.wanandroid.com/";

    /**
     * 根据各种配置创建出Retrofit
     *
     * @return 返回创建好的Retrofit
     */
    public static Retrofit getOnlineCookieRetrofit() {
        // OKHttp客户端
        OkHttpClient.Builder httpBuilder = new OkHttpClient.Builder();
        // 各种参数配置
        OkHttpClient okHttpClient = httpBuilder
                .addNetworkInterceptor(new StethoInterceptor())
                .readTimeout(10000, TimeUnit.SECONDS)
                .connectTimeout(10000, TimeUnit.SECONDS)
                .writeTimeout(10000, TimeUnit.SECONDS)
                .build();


        return new Retrofit.Builder().baseUrl(BASE_URL)
                .client(okHttpClient)

                // 添加一个json解析的工具
                .addConverterFactory(GsonConverterFactory.create(new Gson()))
                // 添加rxjava处理工具
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())

                .build();
    }
}


布局非常简单,就是两个button,点击获取数据然后将数据显示下面textview里面。
篇幅不能弄太多,上面的东西其实不看也行。

api = HttpUtil.getOnlineCookieRetrofit().create(WangAndroidApi.class);
        RxView.clicks(btn1)
                .throttleFirst(2000,TimeUnit.MILLISECONDS)
                //给下面的代码安排io线程
                .observeOn(Schedulers.io())
                //flatMap自己本身可以作为ObservableSource事件源往下传递
                .flatMap(new Function<Object, ObservableSource<ProjectBean>>() {
                    @Override
                    public ObservableSource<ProjectBean> apply(Object o) throws Exception {
                        return api.getProject();
                    }
                })
                .map(new Function<ProjectBean, ProjectBean>() {
                    @Override
                    public ProjectBean apply(ProjectBean bean) throws Exception {
                        return bean;
                    }
                })
                //给下面安排主线程
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<ProjectBean>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        //持有中断当前流的disposable
                        disposable = d;
                    }

                    @Override
                    public void onNext(ProjectBean projectBean) {
                        //拿到数据显示到textView上
                        textView.setText(projectBean.getData().toString());
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.v(TAG, e.toString());
                    }

                    @Override
                    public void onComplete() {
                        //数据发送完了
                        }
                     });

(我看的Rxbingding版本2.1.1确实是这样,同事的3.x版本没有报错,最新版本没有这个问题,写在这里可以加深理解。)
这里面为什么要使用flatMap和一个Map,是因为要在这里说明一下它们之间的一个不同点。

当我们使用RxView这样的操作符的时候传递下来的是一个没有实现ObservableSource的Observable,实际上在Rxjava中流传递Observable都是要实现了ObservableSource接口,如果你不实现这个接口,你怎么使用ObservableSource的实现方法subscribe将对象往上传递呢,所以这里用了一个flatMap操作符,它的返回对象实现了ObservableSource,之后map才能正常使用,它接收的是:ObservableSource《T》 source

它没有实现ObservableSource接口,而我们的map操作符要一个实现了ObservableSource接口的Observable,这是不行的,无法往下传递了。

这是一个正常调用代码,里面没有什么难点,直接看过去就行了。

下面我们要自定义一个RxView这样的操作符。

//我的MyView里面实现了一个操作符(函数),首先是静态直接使用,它需要返回一个Observable
public class MyRxView {
    //这里是Object,不传递泛型了,<T>可以去掉 接收一个View
    public static <T> Observable<T> Myclick(View view){
        return new ViewClickObservable<>(view);
    }
}

我们看一下ViewClickObservable的要求

1、它必须返回一个Observable,得实现Observable,在它的subscribeActual方法往下拆包,调用传递上来的对象调用它的onNext方法,因为它是源头,没有发射器,要自己调用。

2、点击效果必须可以中断,需要给下一层的对象赋值disposable

public class ViewClickObservable<T> extends Observable<T> {
    //持有上一层传递过来的对象,这里的泛型其实都可以写成Object
    private final View view;
    //我们的事件
    private static Object EVENT;

    ViewClickObservable(View view){
        this.view = view;
        EVENT = view;
    }

    //实现下一层传递方法
    @Override
    protected void subscribeActual(Observer<? super T> observer) {
        //根据操作符的原则,先包裹一层
//        CreateEmitter<T> parent = new CreateEmitter<T>(observer);
        //给下一层的disposable赋值
//        observer.onSubscribe(parent);

        MyListener myListener = new MyListener(view ,observer);
        observer.onSubscribe(myListener);
        //这个view就是上一层的对象,在这里不用往上传递了,上一层不是Observable,我自己就是第一层Observable
        // 在Rxjava中是使用source.subscribe(当前对象) 往上传递,这里是源头,直接往下拆包
        this.view.setOnClickListener(myListener);
    }
    //这里没有实现Observer,这个包裹没有自己的onNext等方法,因为不用再往上传递了,我自己就是事件源头了
    //实际的Rxjava的Creae操作符是创建了一个发射器,并且自己实现了ObservableSource
    //瞄了一眼Rxjava的RxView操作符,发现它也是这样做的,懒得去弄了。
    static final class MyListener implements View.OnClickListener, Disposable {
        private final View view;
        private Observer observer;
        private final AtomicBoolean isDisposable = new AtomicBoolean();

        public MyListener(View view, Observer observer){
            this.view = view;
            this.observer = observer; //存一份下一层对象
        }

        @Override
        public void onClick(View v) {
            if (!isDisposed()) {
                observer.onNext(EVENT);
            }
        }

        //如何用户调用中断
        @Override
        public void dispose() {
            //旧值替换新值,如果成功,说明旧值是false我执行之后变成true
            if (isDisposable.compareAndSet(false ,true)) {
                Log.v("ViewClickObservable","isDisposable:" + isDisposable);
                //主线程,很好地中断
                if (Looper.myLooper() == Looper.getMainLooper()) {
                    view.setOnClickListener(null);
                } else { //通过handle切换之后再中断
//                    new Handler(Looper.getMainLooper()) {
//                        @Override
//                        public void handleMessage(@NonNull Message msg) {
//                            view.setOnClickListener(null);
//                        }
//                    };
                    //用一下Rxjava的.observeOn(AndroidSchedulers.mainThread()) 里面的handle
//                    HandlerScheduler.scheduleDirect 不是静态方法,类也不是public 且final修饰

                    //直接查看HandlerScheduler被谁实例化了找到下面调用路劲
                    AndroidSchedulers.mainThread().scheduleDirect(new Runnable() {
                        @Override
                        public void run() {
                            view.setOnClickListener(null);
                        }
                    });
                }

            }
        }

        @Override
        public boolean isDisposed() {
            return false;
        }
    }

}

写好之后我们直接将RxView替换成我们自己写的

MyRxView.Myclick(btn2)
                .throttleFirst(2000, TimeUnit.MILLISECONDS)
                .observeOn(Schedulers.io())
                //这里不能map,上面解释过了
               .flatMap(new Function<Object, ObservableSource<ProjectBean>>() {
                   @Override
                   public ObservableSource<ProjectBean> apply(Object o) throws Exception {
                       return api.getProject();
                   }
               })
              	//上面传递下来了一个总数据javaBean,里面有很多个data,是一个集合
              	//fromIterable分发了集合里面所有的data的数量事件往下传递
                .flatMap(new Function<ProjectBean, ObservableSource<ProjectBean.DataBean>>() {
                    @Override
                    public ObservableSource<ProjectBean.DataBean> apply(ProjectBean projectBean) throws Exception {
                        return Observable.fromIterable(projectBean.getData());
                    }
                })
                //每收到一个data也就是dataBean,获取它的ID,使用它的ID去获取子接口的数据
                //同样的这里会接收到上面分发了集合的size的数量的,也是继续每接收一个往下传递一个
                .flatMap(new Function<ProjectBean.DataBean, ObservableSource<ProjectItem>>() {
                    @Override
                    public ObservableSource<ProjectItem> apply(ProjectBean.DataBean dataBean) throws Exception {
                        return api.getProjectItem(1, dataBean.getId());
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<ProjectItem>() {
                    @Override
                    public void accept(ProjectItem projectItem) throws Exception {
                    	//最终接收size数量的projectItem
                        textView.setText(projectItem.getData().toString());
                    }
                });

操作符flatMap

.flatMap(new Function<Object, ObservableSource<ProjectBean>>() {
                    @Override
                    public ObservableSource<ProjectBean> apply(Object o) throws Exception {
                        return api.getProject();
                    }
                })

它实现了一个接口:

public interface Function<T, R> {
    /**
     * Apply some calculation to the input value and return some other value.
     * @param t the input value
     * @return the output value
     * @throws Exception on error
     */
    R apply(@NonNull T t) throws Exception;
}

接收Object,上面传递下来的流,然后返回ObservableSource,返回一个新的事件源或者流,新的流是: return api.getProject();

下面又再次调用flatMap

 .flatMap(new Function<ProjectBean, ObservableSource<ProjectBean.DataBean>>() {
                    @Override
                    public ObservableSource<ProjectBean.DataBean> apply(ProjectBean projectBean) throws Exception {
                        return Observable.fromIterable(projectBean.getData());
                    }
                })

这次返回的是 return Observable.fromIterable(projectBean.getData());,从方法名我们猜测难道是一个数组?进源码看看

 @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.NONE)
    public static <T> Observable<T> fromIterable(Iterable<? extends T> source) {
        ObjectHelper.requireNonNull(source, "source is null");
        return RxJavaPlugins.onAssembly(new ObservableFromIterable<T>(source));
    }

RxJavaPlugins.onAssembly是个hook,我们继续跟进:

  final Iterable<? extends T> source;
    public ObservableFromIterable(Iterable<? extends T> source) {
        this.source = source;
    }

跟紧我们的数据源,我们继续跟进source

  @Override
    public void subscribeActual(Observer<? super T> s) {
        Iterator<? extends T> it;
        try {
       	 	//持有了我们的数据源
            it = source.iterator();
        } catch (Throwable e) {
            Exceptions.throwIfFatal(e);
            EmptyDisposable.error(e, s);
            return;
        }
        boolean hasNext;
        try {
            hasNext = it.hasNext();
        } catch (Throwable e) {
            Exceptions.throwIfFatal(e);
            EmptyDisposable.error(e, s);
            return;
        }
        if (!hasNext) {
            EmptyDisposable.complete(s);
            return;
        }
		//上面大多是代码健壮性判断,直接看这里
        FromIterableDisposable<T> d = new FromIterableDisposable<T>(s, it);
        s.onSubscribe(d);

        if (!d.fusionMode) {
            d.run();
        }
    }

通过 it = source.iterator(); 让it持有了我们的数据源,之后又运行了代码:
FromIterableDisposable d = new FromIterableDisposable(s, it);

它是一个静态内部类:

 static final class FromIterableDisposable<T> extends BasicQueueDisposable<T> {
		...
		//do while循环,while (hasNext),当里面还有值的话就一直执行
       do {
                if (isDisposed()) {
                    return;
                }
                T v;

                try {
                	//取出每一个值
                    v = ObjectHelper.requireNonNull(it.next(), "The iterator returned a null value");
                } catch (Throwable e) {
                    Exceptions.throwIfFatal(e);
                    actual.onError(e);
                    return;
                }
				//往下传递
				//通过前面三篇的学习应该知道actual是我们下一层的对象,每一个包裹里面的取值名字都一样
                actual.onNext(v);

                if (isDisposed()) {
                    return;
                }
                try {
                    hasNext = it.hasNext();
                } catch (Throwable e) {
                    Exceptions.throwIfFatal(e);
                    actual.onError(e);
                    return;
                }
            } while (hasNext);

            if (!isDisposed()) {
                actual.onComplete();
            }
    }

可以看到 final Iterator<? extends T> it;持有了我们的数据源,循环调用了回调方法将我们的数据分别发送给下游,回到我们的代码中。

接下来又再次使用了flatMap

 .flatMap(new Function<ProjectBean.DataBean, ObservableSource<ProjectItem>>() {
                    @Override
                    public ObservableSource<ProjectItem> apply(ProjectBean.DataBean dataBean) throws Exception {
                        return api.getProjectItem(1,dataBean.getId());
                    }
                }

从上面我们知道是循环持续发送了所有的数据,众多的itemBean,每一个都是一个新的流,那么下面肯定也是会不停地接收众多的流,接收每一个itenBean之后我们又转换发送了新的流:api.getProjectItem(1,dataBean.getId()); 我们通过接收到的数据获取它们的ID,来调用我们的获取子数据的api,然后继续往下传递。

.observeOn(AndroidSchedulers.mainThread())
切换成主线程

.subscribe
关联起观察者

new Consumer<ProjectItem>() {
                    @Override
                    public void accept(ProjectItem projectItem) throws Exception {
                        textView.setText(projectItem.getData().toString());
                    }
                }

看一下被观察者实现了Consumer的接口代码

static final class ObserverOnNext<T> implements Consumer<T> {
        final Observer<T> observer;

        ObserverOnNext(Observer<T> observer) {
            this.observer = observer;
        }

        @Override
        public void accept(T v) throws Exception {
            observer.onNext(v);
        }
    }

accept可以当做onNext,它会接收接收所有的流,数量就是上面Observable.fromIterable(projectBean.getData())中projectBean.getData的数组长度的数量

下面我们来看一下doOnNext操作符

Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                e.onNext("aaa");
            }
        })
                .doOnNext(new Consumer<String>() {
                    @Override
                    public void accept(String s) throws Exception {
                        Log.d(TAG, "accept: " + s);
                    }
                })
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(String s) {
                        Log.d(TAG, "onNext: " + s);
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });

doOnNext方法这里我啥都没做,就输出了上游传递下来的值,看源码:

 @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.NONE)
    public final Observable<T> doOnNext(Consumer<? super T> onNext) {
    	//看这里
        return doOnEach(onNext, Functions.emptyConsumer(), Functions.EMPTY_ACTION, Functions.EMPTY_ACTION);
    }
 @CheckReturnValue
    @SchedulerSupport(SchedulerSupport.NONE)
    private Observable<T> doOnEach(Consumer<? super T> onNext, Consumer<? super Throwable> onError, Action onComplete, Action onAfterTerminate) {
        ObjectHelper.requireNonNull(onNext, "onNext is null");
        ObjectHelper.requireNonNull(onError, "onError is null");
        ObjectHelper.requireNonNull(onComplete, "onComplete is null");
        ObjectHelper.requireNonNull(onAfterTerminate, "onAfterTerminate is null");
        								//直接看这里
        return RxJavaPlugins.onAssembly(new ObservableDoOnEach<T>(this, onNext, onError, onComplete, onAfterTerminate));
    }

在ObservableDoOnEach类里面

 @Override
    public void subscribeActual(Observer<? super T> t) {
    	//下游传递过来的对象,直接包裹一层传递给上游,我们知道等会发射器会调用onNext方法往下拆包
        source.subscribe(new DoOnEachObserver<T>(t, onNext, onError, onComplete, onAfterTerminate));
    }

直接看DoOnEachObserver的onNext方法

@Override
        public void onNext(T t) {
            if (done) {
                return;
            }
            try {
            	//看这里
                onNext.accept(t);
            } catch (Throwable e) {
                Exceptions.throwIfFatal(e);
                s.dispose();
                onError(e);
                return;
            }
			//下游的对象,往下拆包
            actual.onNext(t);
        }
//在这个类里面有这么一个成员,就是我们实现的doOnNext实现对象
final Consumer<? super T> onNext; 

输出结果:

2021-02-28 15:30:50.132 6279-6279/com.example.xyztest D/MainActivity: accept: aaa
2021-02-28 15:30:50.132 6279-6279/com.example.xyztest D/MainActivity: onNext: aaa

doOnNext接收了上面传递下来的对象,然后继续往下传递啥都没改变,只是先自己拦截调用自己的accept方法输出对象。
从方法名来解释就是:在onNext方法调用前我先do一些自己想做的事情,不改变流的对象。

Rxjava的操作符非常多,但是其实是根据不同的类型创造的,我们懂得了Rxjava大概原理流程,如果要用到新的不认识的操作符怎么办?可以两步操作:
1、基本了解Rxjava的原理,直接看源码。
2、再百度一下辅助,基本能搞定了。

下面来一张终结图:
在这里插入图片描述
题外话:我的一个朋友说写博文不能篇幅太大,那些写得非常短的反而人气非常旺,但是一个技术点再怎么短小精悍也无法再压缩了啊,再小的话暂时对我来说没有什么意义,因为当前写的主要是一些常见基础技术的总结。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值