RxJava2学习交流

引言:

说到异步操作,我们会想到Android的AsyncTask和Handler。今天我们要说的是RxJava............2

 

观察者模式(Observer)完美的将观察者和被观察的对象分离开。举个例子,用户界面可以作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上。一对多(一对多,即一个被观察者可以被多个观察者监听。)

 

响应式编程在RxJava中,响应式编程具体表现为一个观察者(Observer)订阅一个可观察对象(Observable),通过创建可观察对象发射数据流,经过一系列操作符(Operators)加工处理和线程调度器(Scheduler)在不同线程间的转发,最后由观察者接受并做出响应的一个过程

 

RxJava2的基本使用

在 build.gradle 中加上:

compile 'io.reactivex.rxjava2:rxjava:2.0.1'

compile 'io.reactivex.rxjava2:rxandroid:2.0.1'

创建RxJava三步曲

1.创建被观察者对象Observable;

2.创建观者对象Observer;

3.创建订阅关系;

                                                                 

     

private void testOne() {
        //创建被观察者对象
        Observable observable = Observable.create(new ObservableOnSubscribe() {
            @Override
            public void subscribe(ObservableEmitter e) throws Exception {
                e.onNext("hello");
                Log.i("testOne", "发送 hello");
                e.onNext("world");
                Log.i("testOne", "发送 world");
                e.onComplete();
                Log.i("testOne", "调用 onComplete");
            }
        });
        //创建观者对象
        Observer observer = new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {
                Log.d("testOne", "onSubscribe");
                disposable = d;
            }

            @Override
            public void onNext(String s) {
                Log.d("testOne", "onNext data is :" + s);
                if (s.equals("hello")) {
                    disposable.dispose();//取消订阅
                }
            }

            @Override
            public void onError(Throwable e) {
                Log.d("testOne", "onError data is :" + e.toString());
            }

            @Override
            public void onComplete() {
                Log.d("testOne", "onComplete");
            }
        };
        //创建订阅关系
        observable.subscribe(observer);
    }

onNext:用来发送数据,可多次调用,每调用一次发送一条数据
onError:用来发送异常通知,只发送一次,若多次调用只发送第一条
onComplete:用来发送完成通知,只发送一次,若多次调用只发送第一条

onError与onComplete互斥,两个方法只能调用一个不能同时调用

 

RxJava2的线程调度器

Scheduler(调度器),它是RxJava用来控制线程

当我们没有设置的时候,RxJava遵循哪个线程产生就在哪个线程消费的原则,也就是说线程不会产生变化,始终在同一个。

但是我们一般使用RxJava都是后台执行,前台调用

 

RxJava 线程调度器

说明

Schedulers.io( )

用于IO密集型的操作,例如读写SD卡文件,查询数据库,访问网络等,具有线程缓存机制,在此调度器接收到任务后,先检查线程缓存池中,是否有空闲的线程,如果有,则复用,如果没有则创建新的线程,并加入到线程池中,如果每次都没有空闲线程使用,可以无上限的创建新线程。

Schedulers.newThread( )

在每执行一个任务时创建一个新的线程,不具有线程缓存机制,因为创建一个新的线程比复用一个线程更耗时耗力,虽然使用Schedulers.io( )的地方,都可以使用Schedulers.newThread( ),但是,Schedulers.newThread( )的效率没有Schedulers.io( )高。

Schedulers.computation()

用于CPU 密集型计算任务,即不会被 I/O 等操作限制性能的耗时操作,例如xml,json文件的解析,Bitmap图片的压缩取样等,具有固定的线程池,大小为CPU的核数。不可以用于I/O操作,因为I/O操作的等待时间会浪费CPU。

Schedulers.trampoline()

在当前线程立即执行任务,如果当前线程有任务在执行,则会将其暂停,等插入进来的任务执行完之后,再将未完成的任务接着执行。

Schedulers.single()

拥有一个线程单例,所有的任务都在这一个线程中执行,当此线程中有任务执行时,其他任务将会按照先进先出的顺序依次执行。

Scheduler.from(@NonNull Executor executor)

指定一个线程调度器,由此调度器来控制任务的执行策略

AndroidSchedulers.mainThread()

在Android UI线程中执行任务,为Android开发定制。RxAndroid 提供

注:在RxJava2中,废弃了RxJava1中的Schedulers.immediate( )在RxJava1中,Schedulers.immediate( )的作用为在当前线程立即执行任务,功能等同于RxJava2中的Schedulers.trampoline( )。而Schedulers.trampoline( )在RxJava1中的作用是当其它排队的任务完成后,在当前线程排队开始执行接到的任务,有点像RxJava2中的Schedulers.single(),但也不完全相同,因为Schedulers.single()不是在当前线程而是在一个线程单例中排队执行任务。

private void testTwo() {
        Observable.create(new ObservableOnSubscribe() {
            @Override
            public void subscribe(ObservableEmitter e) throws Exception {
                Log.e("testTwo", "observable work thread is" + Thread.currentThread().getName());
                e.onNext("hello");
                e.onNext("world");
                e.onComplete();
            }
        }).subscribeOn(Schedulers.io())//切换到io线程
                .observeOn(AndroidSchedulers.mainThread())//切换到主线程
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.e("testTwo", "Observer onSubscribe work thread is" + Thread.currentThread().getName());
                        disposable = d;
                    }

                    @Override
                    public void onNext(String s) {
                        Log.e("testTwo", "Observer onNext work thread is" + Thread.currentThread().getName());
                        Log.d("testTwo", "onNext data is :" + s);
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d("testTwo", "onError data is :" + e.toString());
                    }

                    @Override
                    public void onComplete() {
                        Log.d("testTwo", "onComplete");
                    }
                });
    }

 

RxJava2的操作符

RxJava的强大性就来自于它所定义的操作符。

操作符图谱

                                        

 

                                                                

 

场景1:做一个倒计时发送验证码的按钮

Demo中所有到的操作符:

操作符

说明

interval

延时几秒,每隔几秒开始执行

take

超过多少秒停止执行

map

类型转换

doOnSubscribe

在执行的过程中

public void testThree() {
        final long count = 10; // 设置10秒
        Observable.interval(0, 1, TimeUnit.SECONDS)//延时几秒,每隔几秒开始执行
                .take(count + 1)//超过多少秒停止执行
                .map(new Function<Long, String>() {//类型转换 map操作符通过指定一个Func对象,将Observable转换为一个新的Observable对象并发射,观察者将收到新的Observable处理。
                    @Override
                    public String apply(Long aLong) throws Exception {
                        Log.i("testThree", "aLong=" + aLong);
                        return String.valueOf(count - aLong).toString();
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())//在主线程运行
                .doOnSubscribe(new Consumer<Disposable>() {//在执行的过程中
                    @Override
                    public void accept(@NonNull Disposable disposable) throws Exception {
                        button.setEnabled(false);
                        button.setTextColor(Color.GRAY);
                    }
                })
                .subscribe(new Observer<String>() {//订阅
                    @Override
                    public void onSubscribe(Disposable d) {
                    }

                    @Override
                    public void onNext(String aLong) {
                        button.setText(aLong);
                    }

                    @Override
                    public void onError(Throwable e) {
                    }

                    @Override
                    public void onComplete() {
                        button.setEnabled(true);
                        button.setTextColor(Color.RED);
                        button.setText("发送验证码");
                    }
                });
    }

场景2:我们假设有这个一场景:每个学校都有成绩统计系统,有这样一个需求,我们要抽取一个班,打印该班的每个同学的每一门课程成绩。

操作符

说明

fromIterable

逐次发射list的中的数据

flatMap

将一个Observable转换为另一个Observable发射出去

private void newTest() {
        Observable.fromIterable(getStudents())//逐次发射list的中的数据
                .flatMap(new Function<Student, ObservableSource<Source>>() {
                    @Override
                    public ObservableSource<Source> apply(Student student) throws Exception {
                        return Observable.fromIterable(student.mSources);
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Source>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(Source source) {
                        String content = "sourceName:" + source.name + " source score:" + source.score;
                        Log.i("newTest", content);
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

场景...:RxJava的操作符很强大,根据不同场景不同需求,自由组合,天空才是它的极限

总结:

传统是自己主动控制去得到数据,主动控制数据得流向(展示/参数),然后将数据和数据的流向代码组装起来。Rxjava中的响应式编程是被观察者拿到数据主动传递给观察者,将展示层和数据处理层分离,解耦了各个模块,通过不同线程操控代码运作配合变换过滤等api操作实现数据流传播。

异步、简洁(逻辑、代码读写)。内部支持多线程操作,强大的map和flatmap保证了依赖上一次接口数据进行二次处理时不会发生嵌套,将各个模块分离。随着程序逻辑的复杂,依然保持简洁。解耦了各个模块操作,单一化,不嵌套

源码:

package com.example.semisky.rxjavademostu;

import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

import org.reactivestreams.Publisher;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import io.reactivex.Flowable;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.ObservableSource;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;

public class MainActivity extends AppCompatActivity {

    private Button button;
    private Disposable disposable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = (Button) findViewById(R.id.send_sms);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //testOne();
                //testTwo();
                //testThree();
                //oldTest();
                newTest();
            }
        });
    }

    private void testOne() {
        //创建被观察者对象
        Observable observable = Observable.create(new ObservableOnSubscribe() {
            @Override
            public void subscribe(ObservableEmitter e) throws Exception {
                e.onNext("hello");
                Log.i("testOne", "发送 hello");
                e.onNext("world");
                Log.i("testOne", "发送 world");
                e.onComplete();
                Log.i("testOne", "调用 onComplete");
            }
        });
        //创建观者对象
        Observer observer = new Observer<String>() {
            @Override
            public void onSubscribe(Disposable d) {
                Log.d("testOne", "onSubscribe");
                disposable = d;
            }

            @Override
            public void onNext(String s) {
                Log.d("testOne", "onNext data is :" + s);
                if (s.equals("hello")) {
                    disposable.dispose();//取消订阅
                }
            }

            @Override
            public void onError(Throwable e) {
                Log.d("testOne", "onError data is :" + e.toString());
            }

            @Override
            public void onComplete() {
                Log.d("testOne", "onComplete");
            }
        };
        //创建订阅关系
        observable.subscribe(observer);
    }

    private void testTwo() {
        Observable.create(new ObservableOnSubscribe() {
            @Override
            public void subscribe(ObservableEmitter e) throws Exception {
                Log.e("testTwo", "observable work thread is" + Thread.currentThread().getName());
                e.onNext("hello");
                e.onNext("world");
                e.onComplete();
            }
        }).subscribeOn(Schedulers.io())//切换到io线程
                .observeOn(AndroidSchedulers.mainThread())//切换到主线程
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                        Log.e("testTwo", "Observer onSubscribe work thread is" + Thread.currentThread().getName());
                        disposable = d;
                    }

                    @Override
                    public void onNext(String s) {
                        Log.e("testTwo", "Observer onNext work thread is" + Thread.currentThread().getName());
                        Log.d("testTwo", "onNext data is :" + s);
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d("testTwo", "onError data is :" + e.toString());
                    }

                    @Override
                    public void onComplete() {
                        Log.d("testTwo", "onComplete");
                    }
                });
    }

    public void testThree() {
        final long count = 10; // 设置10秒
        Observable.interval(0, 1, TimeUnit.SECONDS)//延时几秒,每隔几秒开始执行
                .take(count + 1)//超过多少秒停止执行
                .map(new Function<Long, String>() {//类型转换 map操作符通过指定一个Func对象,将Observable转换为一个新的Observable对象并发射,观察者将收到新的Observable处理。
                    @Override
                    public String apply(Long aLong) throws Exception {
                        Log.i("testThree", "aLong=" + aLong);
                        return String.valueOf(count - aLong).toString();
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())//在主线程运行
                .doOnSubscribe(new Consumer<Disposable>() {//在执行的过程中
                    @Override
                    public void accept(@NonNull Disposable disposable) throws Exception {
                        button.setEnabled(false);
                        button.setTextColor(Color.GRAY);
                    }
                })
                .subscribe(new Observer<String>() {//订阅
                    @Override
                    public void onSubscribe(Disposable d) {
                    }

                    @Override
                    public void onNext(String aLong) {
                        button.setText(aLong);
                    }

                    @Override
                    public void onError(Throwable e) {
                    }

                    @Override
                    public void onComplete() {
                        button.setEnabled(true);
                        button.setTextColor(Color.RED);
                        button.setText("发送验证码");
                    }
                });
    }

    class Student {
        public String name;//学生名字
        public int id;
        public List<Source> mSources;//每个学生的所有课程

        public Student(String name, int id, List<Source> sources) {
            this.name = name;
            this.id = id;
            mSources = sources;
        }
    }

    class Source {
        public int sourceId;//id
        public String name;//课程名
        public int score;//成绩

        public Source(int sourceId, String name, int score) {
            this.sourceId = sourceId;
            this.name = name;
            this.score = score;
        }
    }

    private void oldTest() {
        //开启一个线程
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 模拟从服务器获取班级所有同学信息
                List<Student> students = getStudents();

                for (int i = 0; i < students.size(); i++) {
                    List<Source> sources = students.get(i).mSources;
                    Log.i("oldTest====", sources.size() + "name:" + students.get(i).name);
                    for (int index = 0; index < sources.size(); index++) {
                        final Source source = sources.get(index);
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                //主线程更改UI
                                String content = "sourceName:" + source.name + " source score:" + source.score;
                                Log.i("oldTest", content);
                            }
                        });

                    }
                }
            }
        }).start();
    }

    private void newTest() {
        Observable.fromIterable(getStudents())//逐次发射list的中的数据
                .flatMap(new Function<Student, ObservableSource<Source>>() {
                    @Override
                    public ObservableSource<Source> apply(Student student) throws Exception {
                        return Observable.fromIterable(student.mSources);
                    }
                })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<Source>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(Source source) {
                        String content = "sourceName:" + source.name + " source score:" + source.score;
                        Log.i("newTest", content);
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

    private List<Student> getStudents() {
        List<Student> students = new ArrayList<>();
        for (int i = 0; i < 2; i++) {
            List<Source> sources = new ArrayList<>();
            for (int j = 0; j < 3; j++) {
                sources.add(new Source(j, "学科" + j, 80 + j));
            }
            students.add(new Student("李" + i, i, sources));
        }
        return students;
    }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值