RxJava2 基础使用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cuizehui123/article/details/80631970

RxJava

summary

  1. 介绍订阅模式/基本语法
  2. 介绍线程切换的订阅
  3. 介绍变化操作符
  4. 背压解决方法和操作符
  5. 介绍和retrofit使用
  6. Lambda表达式

观察与消费者

  Observable<Integer> observable = Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> e) throws Exception {
                e.onNext(1);
                e.onNext(2);
                e.onNext(3);
            }
        });

        Observer observer = new Observer() {
            @Override
            public void onSubscribe(Disposable d) {
            }

            @Override
            public void onNext(Object value) {
                Log.d(":", value.toString());
            }
            @Override
            public void onError(Throwable e) {
            }
            @Override
            public void onComplete() {
            }
        };
        //
        Consumer consumer = new Consumer() {
            @Override
            public void accept(Object o) throws Exception {

            }
        };
        observable.subscribe(consumer);

        observable.subscribe(observer);

线程切换

private void threadRxjava2() {
        Observable<Integer> observable = Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> e) throws Exception {
                e.onNext(1);
            }
        });
        Consumer consumer = new Consumer() {
            @Override
            public void accept(Object o) throws Exception {
                Log.d("处理事件", "");
            }
        };
        /**
         * Schedulers.io() 代表io操作的线程, 通常用于网络,读写文件等io密集型的操作
         Schedulers.computation() 代表CPU计算密集型的操作, 例如需要大量计算的操作
         Schedulers.newThread() 代表一个常规的新线程
         AndroidSchedulers.mainThread() 代表Android的主线程
         */
        //只有初次指定有效其余无效
        //订阅事件执行在新线程
        observable.subscribeOn(Schedulers.newThread())
                //每执行一次切换下游线程,都会产生效果
                //观察事件执行在主线程
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(consumer);

    }

操作符

singleobserver/completableobserver

如果你使用一个单一连续事件流,即只有一个onNext事件,接着就触发onComplete或者onError,这样你可以使用Single。

如果你的观察者连onNext事件都不关心,你可以使用Completable,他只有onComplete和onError两个事件

Disposable

用于解除订阅
创建一个可被 CompositeDisposable 管理的 observer
生命周期可控制订阅和解除订阅
避免发生内存泄漏

 private static final String TAG = DisposableExampleActivity.class.getSimpleName();
    Button btn;
    TextView textView;
    private final CompositeDisposable disposables = new CompositeDisposable();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_example);
        btn = (Button) findViewById(R.id.btn);
        textView = (TextView) findViewById(R.id.textView);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                doSomeWork();
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        disposables.clear(); // do not send event after activity has been destroyed
    }

    /*
     * Example to understand how to use disposables.
     * disposables is cleared in onDestroy of this activity.
     */
    void doSomeWork() {
        disposables.add(sampleObservable()
                // Run on a background thread
                .subscribeOn(Schedulers.io())
                // Be notified on the main thread
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeWith(new DisposableObserver<String>() {
                    @Override
                    public void onComplete() {
                        textView.append(" onComplete");
                        textView.append(AppConstant.LINE_SEPARATOR);
                        Log.d(TAG, " onComplete");
                    }

                    @Override
                    public void onError(Throwable e) {
                        textView.append(" onError : " + e.getMessage());
                        textView.append(AppConstant.LINE_SEPARATOR);
                        Log.d(TAG, " onError : " + e.getMessage());
                    }

                    @Override
                    public void onNext(String value) {
                        textView.append(" onNext : value : " + value);
                        textView.append(AppConstant.LINE_SEPARATOR);
                        Log.d(TAG, " onNext value : " + value);
                    }
                }));
    }

    static Observable<String> sampleObservable() {
        return Observable.defer(new Callable<ObservableSource<? extends String>>() {
            @Override
            public ObservableSource<? extends String> call() throws Exception {
                // Do some long running operation
                SystemClock.sleep(2000);
                return Observable.just("one", "two", "three", "four", "five");
            }
        });
    }

定时任务调度操作符:timer/interval/delay

实现定时调度任务的操作符:

  • timer:创建型操作符,用于延时执行任务。

    Observable.timer(2, TimeUnit.SECONDS);
  • interval:创建型操作符,用于周期执行任务。 间隔几秒后执行

    //默认第一次个任务需要延时和指定间隔相同的时间。
    Observable.interval(0, 2, TimeUnit.SECONDS);
  • delay:辅助型操作,用于延时传递数据。

    Observable.delay(2, TimeUnit.SECONDS)

过滤类操作符 take/skip

  • filter

    Observable.just(1, 2, 3, 4, 5, 6)
                .filter(new Predicate<Integer>() {
                    @Override
                    public boolean test(Integer integer) throws Exception {
                        return integer % 2 == 0;
                    }
                })
                .subscribe(getObserver());
  • take 前的事件

  • skip跳过前几个事件
  • last 发射默认最后一个,如果没有则发射设置的默认值

buffer

将要发射的数据封装成多个缓冲区,每次发射一个缓冲区

        Observable<List<String>> buffered = getObservable().buffer(3, 1);

        // 3 means,  it takes max of three from its start index and create list
        // 1 means, it jumps one step every time
        // so the it gives the following list
        // 1 - one, two, three
        // 2 - two, three, four
        // 3 - three, four, five
        // 4 - four, five
        // 5 - five

map

ObservableEmitter发射器,发射规定参数范型的事件给下游

发射 变换 处理:

public class MapExampleActivity extends AppCompatActivity {

    private static final String TAG = MapExampleActivity.class.getSimpleName();
    Button btn;
    TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_example);
        btn = (Button) findViewById(R.id.btn);
        textView = (TextView) findViewById(R.id.textView);

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

    /*
    * Here we are getting ApiUser Object from api server
    * then we are converting it into User Object because
    * may be our database support User Not ApiUser Object
    * Here we are using Map Operator to do that
    */
    private void doSomeWork() {
        getObservable()
                // Run on a background thread
                .subscribeOn(Schedulers.io())
                // Be notified on the main thread
                .observeOn(AndroidSchedulers.mainThread())
                .map(new Function<List<ApiUser>, List<User>>() {

                    @Override
                    public List<User> apply(List<ApiUser> apiUsers) throws Exception {
                        return Utils.convertApiUserListToUserList(apiUsers);
                    }
                })
                .subscribe(getObserver());
    }

    private Observable<List<ApiUser>> getObservable() {
        return Observable.create(new ObservableOnSubscribe<List<ApiUser>>() {
            @Override
            public void subscribe(ObservableEmitter<List<ApiUser>> e) throws Exception {
                if (!e.isDisposed()) {
                    e.onNext(Utils.getApiUserList());
                    e.onComplete();
                }
            }
        });
    }

    private Observer<List<User>> getObserver() {
        return new Observer<List<User>>() {

            @Override
            public void onSubscribe(Disposable d) {
                Log.d(TAG, " onSubscribe : " + d.isDisposed());
            }

            @Override
            public void onNext(List<User> userList) {
                textView.append(" onNext");
                textView.append(AppConstant.LINE_SEPARATOR);
                for (User user : userList) {
                    textView.append(" firstname : " + user.firstname);
                    textView.append(AppConstant.LINE_SEPARATOR);
                }
                Log.d(TAG, " onNext : " + userList.size());
            }

            @Override
            public void onError(Throwable e) {
                textView.append(" onError : " + e.getMessage());
                textView.append(AppConstant.LINE_SEPARATOR);
                Log.d(TAG, " onError : " + e.getMessage());
            }

            @Override
            public void onComplete() {
                textView.append(" onComplete");
                textView.append(AppConstant.LINE_SEPARATOR);
                Log.d(TAG, " onComplete");
            }
        };
    }
}

flatmap

将上游事件返回的对象进行变换和拆解,flatmap为按照顺序。

private void flatMapRxJava() {
        Observable.create(new ObservableOnSubscribe<Integer>() {
            @Override
            public void subscribe(ObservableEmitter<Integer> e) throws Exception {
                e.onNext(1);
                e.onNext(2);
            }
            //flatmap根据上游事件的个数执行相应的次数。 <key,Values>
        }).flatMap(new Function<Integer, ObservableSource<String>>() {
            @Override
            //下面的代码示例展示了 JDK 5.0 中集合框架中的 Map 接口的定义的一部分:
            //  public interface Map<K, V> {
            //  public void put(K key, V value);
            //  public V get(K key);
            //  }
            //范型函数作用是:必须在定义或实例化 Map 类型的变量时为 K 和 V 提供具体的值
            public ObservableSource<String> apply(Integer integer) throws Exception {
                ArrayList list=new ArrayList();
                for (int i = 0; i < 3; i++) {
                    list.add("I am value " + integer);
                }
                return Observable.fromIterable(list).delay(10, TimeUnit.MILLISECONDS);
            }
        }).subscribe(new Consumer<String>() {
            @Override
            public void accept(String s) throws Exception {
                Log.d("accept",":"+s);
            }
        });
    }

我们可以根据需求,选择相应的简化订阅。只不过传入的对象改为了Consumer。

reduce

要把一个被观察者的所有元素都聚合成单一的元素,可以使用reduce操作符,比如把所有元素都加起来。


getObservable()
.reduce(new BiFunction<Integer, Integer, Integer>() {
@Override
public Integer apply(Integer t1, Integer t2) {
return t1 + t2;
}
})
.subscribe(getObserver());

merge

多个观察者合并但乱序

 /*
     * Using merge operator to combine Observable : merge does not maintain
     * the order of Observable.
     * It will emit all the 7 values may not be in order
     * Ex - "A1", "B1", "A2", "A3", "A4", "B2", "B3" - may be anything
     */
    private void doSomeWork() {
        final String[] aStrings = {"A1", "A2", "A3", "A4"};
        final String[] bStrings = {"B1", "B2", "B3"};

        final Observable<String> aObservable = Observable.fromArray(aStrings);
        final Observable<String> bObservable = Observable.fromArray(bStrings);

        Observable.merge(aObservable, bObservable)
                .subscribe(getObserver());
    }

concat

跟Merge操作符很像,但是这个操作符是能保证输出顺序的
here - first “A1”, “A2”, “A3”, “A4” and then “B1”, “B2”, “B3”

zip

比如一个界面需要展示用户的一些信息, 而这些信息分别要从两个服务器接口中获取, 而只有当两个都获取到了之后才能进行展示, 这个时候就可以用Zip了:

  Observable.zip(getCricketFansObservable(), getFootballFansObservable(),
                new BiFunction<List<User>, List<User>, List<User>>() {
                    @Override
                    public List<User> apply(List<User> cricketFans, List<User> footballFans) throws Exception {
                        return Utils.filterUserWhoLovesBoth(cricketFans, footballFans);
                    }
                })
                // Run on a background thread
                .subscribeOn(Schedulers.io())
                // Be notified on the main thread
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(getObserver());

scan

scan操作符将Observable的结果在BiFunction扫描一遍后交给Observer使用,scan最大的功用是在BiFunction里面的apply里面做一次计算,有条件、有筛选的输出最终结果

  Observable.just(1, 2, 3, 4, 5);
  getObservable()
                    // Run on a background thread
                .subscribeOn(Schedulers.io())
                            // Be notified on the main thread
                            .observeOn(AndroidSchedulers.mainThread())
                            .scan(new BiFunction<Integer, Integer, Integer>() {
                        @Override
                        public Integer apply(Integer int1, Integer int2) throws Exception {
                            return int1 + int2;
                        }
                })
                .subscribe(getObserver());      
    }

最终输出1,3,6,10,15

replay

创建操作符 defer

efer的英文意思就是推迟,在这里是推迟Observable的创建,defer操作符是直到有订阅者订阅时,才通过Observable的工厂方法创建Observable,defer能保证Observable的状态是最新的.


public Observable<String> brandDeferObservable() {
return Observable.defer(new Callable<ObservableSource<? extends String>>() {
@Override
public ObservableSource<? extends String> call() throws Exception {
return Observable.just(brand);
}
});
}

throttleFirst

如果你需要在一段时间内只响应第一次的操作,比如说一段时间内连续点击按钮只执行第一次的点击操作,throttleFirst操作符就可以满足这个需求

 private void doSomeWork() {
        getObservable()
                .throttleFirst(500, TimeUnit.MILLISECONDS)
                // Run on a background thread
                .subscribeOn(Schedulers.io())
                // Be notified on the main thread
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(getObserver());
    }

throttlelast

同上采集最后一个元素

debounce

当一个事件发送出来之后,在约定时间内没有再次发送这个事件,则发射这个事件,如果再次触发了,则重新计算时间。

应用场景举例
需求:在Edittext上添加监听,当里面输入的内容变化后进行搜索。换句话说就是当用户的输入操作停止几秒钟之后再去搜索。

window

swithchmap

replaysubject

publishubject

behavirsubject

asynsubbject

sample

每隔一段时间取出事件

会丢失部分事件;

Backpressure 概念

背部的压力,就是你走得慢了,后面有人推你。
背压是下游控制上游流速的一种手段

flowable+ Subscriber +request拉取式方法解决背压问题

onSubscribe回调的参数不是Disposable而是Subscription,多了行代码

FlowableEmitter

  • BackpressureStrategy.DROP和
  • BackpressureStrategy.LATEST这两种策略.
  • BackpressureStrategy.BUFFER

        Flowable<Integer> observable = Flowable.create(new FlowableOnSubscribe<Integer>() {
            @Override
            public void subscribe(FlowableEmitter<Integer> flowableEmitter) throws Exception {
                flowableEmitter.onNext(1);
                flowableEmitter.onComplete();
            }
        }, BackpressureStrategy.BUFFER);
    //        ,BackpressureStrategy.LATEST);
    //        ,BackpressureStrategy.DROP);
        //设置背压测策略
    
        observable.observeOn(Schedulers.io())
                .subscribeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<Integer>() {
                    @Override
                    public void onSubscribe(Subscription s) {
                        s.request(23);
                    }
    
                    ........
    }
    

Retrofit结合

响应式编程

数据流就像一条河:它可以被观测,被过滤,被操作,或者为新的消费者与另外一条流合并为一条新的流。

猜你喜欢

转载自blog.csdn.net/cuizehui123/article/details/80631970