RxJava
summary
- 介绍订阅模式/基本语法
- 介绍线程切换的订阅
- 介绍变化操作符
- 背压解决方法和操作符
- 介绍和retrofit使用
- 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:创建型操作符,用于延时执行任务。
Observable.timer(2, TimeUnit.SECONDS);
interval:创建型操作符,用于周期执行任务。 间隔几秒后执行
//默认第一次个任务需要延时和指定间隔相同的时间。 Observable.interval(0, 2, TimeUnit.SECONDS);
delay:辅助型操作,用于延时传递数据。
Observable.delay(2, TimeUnit.SECONDS)
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
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
每隔一段时间取出事件
会丢失部分事件;
背部的压力,就是你走得慢了,后面有人推你。
背压是下游控制上游流速的一种手段
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); } ........ }
数据流就像一条河:它可以被观测,被过滤,被操作,或者为新的消费者与另外一条流合并为一条新的流。