RxJava学习笔记

本文为自己学习RxJava的学习笔记,不定时更新,文中资料来源于网上搜集整理,但均为本人一字字亲自敲出来的,为了加深学习记忆,绝无复制粘贴,若文中资料有侵犯到哪位高人的版权,敬请提出,我将在第一时间调整!

*****************RxJava的操作符*******************
  • just(T...):将传入的参数依次发送出来,快捷创建创建事件队列的方法,
    Observable.just("hello","world”);
    等同于
    Observable observable = Observable.create(new Observable.OnSubscribe<String>() {
        @Override
        public void call(Subscriber<? super String> subscriber) {
            subscriber.onNext("hello");
            subscriber.onNext("world");
            subscriber.onCompleted();
        }
    })

  • from(T[]) / from(Iterable<? extends T>) : 将传入的数组或 Iterable 拆分成具体对象后,依次发送出
    String[] words = new String[]{"hello","world"};
    Observable.from(words);
           等同于
Observable observable = Observable.create(new Observable.OnSubscribe<String>() {
    @Override
    public void call(Subscriber<? super String> subscriber) {
        subscriber.onNext("hello");
        subscriber.onNext("world");
        subscriber.onCompleted();
    }
})

})*****************RxJava的其他记录*******************
RxJava的基本实现方式:
Observable即被观察者,它决定了什么时候触发事件以及触发怎样的事件。
Observer即观察者,它决定了事件触发的时候将有怎样的行为。
Observable.create(new Observable.OnSubscribe<String>() {
    @Override
    public void call(Subscriber<? super String> subscriber) {
        subscriber.onNext("hello");
        subscriber.onNext("world");
        subscriber.onCompleted();
    }
})
        .subscribe(new Observer<String>() {
            @Override
            public void onCompleted() {
                Log.d(TAG,"onCompleted")
            }

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

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

除了Observer接口之外,RxJava还内置了一个实现了observer的抽象类:Subscriber.
Observable.create(new Observable.OnSubscribe<String>() {
    @Override
    public void call(Subscriber<? super String> subscriber) {
        subscriber.onNext("hello");
        subscriber.onNext("world");
        subscriber.onCompleted();
    }
})
        .subscribe(new Subscriber<String>() {
            @Override
            public void onCompleted() {
                Log.d(TAG, "onCompleted");
            }

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

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

两种使用方式是一样的。它们的区别对于使用者来说主要有两点:
1.Subscriber新增加了onStart()方法,它会在subscribe刚开始事件还未发送之前被调用,可以用于做一些准备工作,例如数据的清零或者重置。这是一个可选方法,默认情况下它的实现为空。需要注意的是,如果对准备工作有线程要求(如弹出一个转菊花的ProgressBar,就必须在主线程执行),onStart()方法就不适用了,因为它总是在subscribe所发生的线程被调用,而不能指定线程。需要在指定线程来做准备工作,可以使用doOnSubscribe()方法。
2.Subscriber实现了另一个方法unsubscribe(),这个方法被调用后,Subscriber将不再接收事件。一般这个方法调用前,可以使用isUnsubscribed()先判断一下状态。unsubscribe()主要用于解除引用关系,以避免内存泄露的发生。
  • Action
    Action1<String> onNextAction = new Action1<String>() {
        @Override
        public void call(String s) {
            // next()
            Log.d(TAG,s);
        }
    };
    
    Action1<Throwable> onErrorAction = new Action1<Throwable>() {
        @Override
        public void call(Throwable throwable) {
            // ERROR
        }
    };
    
    Action0 onCompletedAction = new Action0() {
        @Override
        public void call() {
            // complete
            Log.d(TAG,"onCompleted");
        }
    };
    
    // 自动创建Subscriber,并使用onNextAction来定义onNext();
    observable.subscribe(onNextAction);
    // 自动创建Subscriber,并使用onNextAction onErrorAction 来定义onNext() onError()
    observable.subscribe(onNextAction,onErrorAction);
    // 自动创建Subscriber,并使用onNextAction onErrorAction  onCompletedAction来定义onNext() onError() onCompleted()
    observable.subscribe(onNextAction,onErrorAction,onCompletedAction);
Action0是RxJava的一个接口,它只有一个方法call(),这个方法是无参数 无返回值 的;由于onCompleted()方法也是无参数无返回值得,因此Action0可以被当成一个包装对象,将onCompleted()的内容打包起来将自己作为一个参数传入subscribe()以实现不完整定义的回调。Action1也是一个借口,它同样只有一个方法call(T t),这个方法也无返回值,但是有一个参数;与Action0同理,由于onNext(T t)和onError(Throwable error)也是单参数无返回值的,因此Action1可以将onNext(t)和onError(error)打包。 RxJava提供了多个ActionX形式的接口,他们可以用以包装不同的无返回值的方法。ActionX的方法是无返回值的。

将字符串数组names中的所有字符串依次打印出来:
String[] names = new String[]{"John","Jim","Tom","Alexander"};
Observable.from(names)
        .subscribe(new Action1<String>() {
            @Override
            public void call(String s) {
                Log.d(TAG,s);
            }
        });

  • 线程控制 —— Scheduler
在不指定线程的情况下,RxJava遵循的是线程不变的原则,即:在哪个线程调用subscribe(),就在哪个线程产生事件;在哪个线程产生事件就在哪个线程消费事件。如果需要切换线程,就需要用到Scheduler(调度器)。RxJava通过它来指定每一段代码应该运行在什么样的线程。RxJava已经内置了几个Scheduler:
  1. Schedulers.immediate():直接在当前线程中运行,相当于不指定线程。这是默认的Scheduler。
  2. Schedulers.newThread():总是启用新线程,并在新线程执行操作。
  3. Schedulers.io():I/O操作(读写文件,读写数据库,联网等)所使用的Scheduler。行为模式跟newThread()的差不多,区别在于io()的内部实现是一个无数量上线的线程池,可以重用空闲的线程,因此多数情况下io()比newThread()更有效率。不要把计算工作放在io()中,可以避免创建不必要的线程。
  4. Schedulers.computation():计算所使用的Scheduler。这个计算指的是cpu密集型计算,即不会被I/O等操作限制性能的操作,例如图形的计算。这个Scheduler使用的是固定的线程池,大小为CPU核心数。不要把I/O操作放在computation()中,否则I/O操作的等待时间会浪费cpu。
  5. 另外,Android还有一个专用的AndroidSchedulers.mainThread(),它制定的操作将在Android主线程运行。
有了这几个Scheduler,就可以使用subscribeOn()和observeOn()两个方法来对线程进行控制。 subscribeOn()指定subscribe()所发生的线程,即Observable.OnSubscribe被激活时所处的线程,或者叫做事件产生的线程。 observeOn()指定Subscriber所运行在的线程。或者叫做事件的消费的线程。
String[] names = new String[]{"John","Jim","Tom","Alexander"};
Observable.from(names)
        // 指定names发生的线程在io()线程,被创建的事件的内容names会在io线程发出
        .subscribeOn(Schedulers.io())
        // 指定Subscriber的回调发生在主线程,故打印将发生在主线程。
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Action1<String>() {
            @Override
            public void call(String s) {
                Log.d(TAG,s);
            }
        });

事实上,这种在subscribe()之前写上两句subscribeOn(Scheduler.io())和observeOn(AndroidSchedulers.mainThread())的使用方式非常常见,它适用于多数的“后台线程取数据,主线程显示”的程序策略。
  • 变换
所谓变化,就是将事件序列中的对象或整个序列进行加工处理,转换成不同的事件或事件序列。
observeOn()指定的是它之后的操作所在的线程。因此如果有多次切换线程的需求,只要在每个想要切换线程的位置调用一次observeOn()即可。不过,不同于observeOn(),subscribeOn()的位置放在哪里都可以,但它是只能调用一次的。当使用了多个subscribeOn()的时候,只有第一个subscribeOn()起作用。
然而,虽然超过一个的subscribeOn()对事件处理的流程没有影响,但在流程之前确是可以利用的。那就是与Subscriber.onStart()方法相对应的Observable.doOnSubscribe()方法,它和Subscriber.onStart()同样是在subscribe()调用后且在事件发送前执行,但区别在于它可以指定线程。默认情况下,doOnSubscribe()执行在subscribe()发生的线程。如果在doOnSubscribe()之后有subscribeOn()方法,则它将执行离他最近的subScribeOn()所指定的线程。如下,在doOnSubscribe()后面跟一个subscribeOn(),就能指定准备工作的线程了。
Observable.just("hello","world")
        .subscribeOn(Schedulers.io())
        .doOnSubscribe(new Action0() {
            @Override
            public void call() {
                // 需要在主线程执行
                showProgressBar();
            }
        })
        // 指定主线程
        .subscribeOn(AndroidSchedulers.mainThread())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Action1<String>() {
            @Override
            public void call(String s) {
                Log.d(TAG,s);
            }
        });
  • Func
    Observable.just("images/sky.png")
            .map(new Func1<String, Bitmap>() {
                @Override
                public Bitmap call(String s) {
                    return getBitmapFromFile(s);
                }
            })
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Action1<Bitmap>() {
                @Override
                public void call(Bitmap bitmap) {
                    iv.setImageBitmap(bitmap);
                }
            });
这里出现了一个叫做Func1的类。它和Action1非常相似,也是RxJava的一个接口,用于包装含有一个参数的方法。 Func跟Action的区别在于,Func包装的是有返回值的方法。另外,和ActionX一样,FuncX也有多个,用于不同参数个数的方法。
  1. map():事件对象的直接变换。它是RxJava最常用的变换。
  2. flatMap():它也是把传入的参数转化之后返回另一个对象。但是跟map()不同的是,flatMap()返回的是个Observable对象,并且这个Observable对象并不是被直接发送到了Subscriber的回调方法中。
  3. throttleFirst():在每次事件触发后的一定时间间隔内丢弃新的事件。常用作去抖动过滤,例如按钮的点击监听事件。

*****************举个例子*******************

假如我现在需要联网加载百度的页面,然后将返回的内容显示在一个TextView上,就可以这么写:

public class MainActivity extends AppCompatActivity {
    private TextView tvFirst;
    private TextView tvResult;
    private ProgressDialog dialog;
    private static final String TAG = "zhangym";
    private Observable<String> mObservable;
    private Subscriber<String> mSubscriber;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        tvFirst = (TextView) findViewById(R.id.tv_fist);
        tvResult = (TextView) findViewById(R.id.tv_result);

        tvFirst.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                showResponseResult();
            }
        });
    }

    private void showResponseResult() {
        // 创建被观察者
        mObservable = Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                HttpURLConnection connection = null;
                try {
                    URL url = new URL("https://www.baidu.com/");
                    connection = (HttpURLConnection) url.openConnection();
                    connection.setRequestMethod("GET");
                    connection.setConnectTimeout(8000);
                    connection.setReadTimeout(8000);
                    InputStream is = connection.getInputStream();
                    BufferedReader reader = new BufferedReader(new InputStreamReader(is));
                    StringBuilder sb = new StringBuilder();
                    String line = null;
                    while ((line = reader.readLine()) != null) {
                        sb.append(line);
                    }

                    // 发送事件
                    subscriber.onNext(sb.toString());
                    subscriber.onCompleted();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        // 创建观察者
        mSubscriber = new Subscriber<String>() {
            @Override
            public void onCompleted() {
                Log.d(TAG, "onCompleted");
                dialog.dismiss();
            }

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

            @Override
            public void onNext(String s) {
                tvResult.setText(s);
            }
        };

        // 指定联网操作在io线程
        mObservable.subscribeOn(Schedulers.io())
                // 事件发送前的准备工作
                .doOnSubscribe(new Action0() {
                    @Override
                    public void call() {
                        dialog = new ProgressDialog(MainActivity.this, ProgressDialog.THEME_DEVICE_DEFAULT_LIGHT);
                        dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
                        dialog.setIndeterminate(true);
                        dialog.show();
                    }
                })
                // 指定doOnSubscribe()的线程为UI线程
                .subscribeOn(AndroidSchedulers.mainThread())
                // 指定Subscriber的线程为UI线程,即在UI线程显示结果
                .observeOn(AndroidSchedulers.mainThread())
                // 订阅事件
                .subscribe(mSubscriber);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 取消订阅,防止内存泄露
        if (!mSubscriber.isUnsubscribed()){
            mSubscriber.unsubscribe();
        }
    }
}


运行效果:由于网速较快,所以ProgressDialog一闪而过,gif图上面看不出来。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值