RxBinding 是一个对android View各种事件的扩展库,把各种view事件转为Observable事件流,使得可以对view事件使用rxjava的各种操作,同时也简化了代码。
.
本文重点:
1.常用的使用场景 (ps: 懂得直接跳过!)
2.要注意的点(比较重要)
3.RxBinding实现分析
4.模仿RxBinding做一个RxAnimation
.
常用的使用场景:
.
1.各种点击事件的去重, 在RxBinding没有出来之前,你可能在开发过程中会遇到这种情况, 比如说点击某个按钮跳转到一个新的Activity, 暂且叫它A吧, 那么你快速点击这个按钮两次,你会发现A创建了两个实例。坑啊!
RxBinding 极好的解决了这个问题!
RxView.clicks(xxButton)
.throttleFirst(500, TimeUnit.MILLISECONDS)
.subscribe(new Action1<Void>() {
@Override
public void call(Void aVoid) {
startActivity(new Intent(MainActivity.this, A.class));
}
});
RxAdapterView.itemClicks(listView)
.throttleFirst(500, TimeUnit.MILLISECONDS)
.subscribe(new Action1<Void>() {
@Override
public void call(Void aVoid) {
startActivity(new Intent(MainActivity.this, A.class));
}
});
.
2.使得代码更简洁,特别是各种View的接口,特别是多个方法的那种,我本来想以TextView为示例的,算了这个都满天飞了,换一个比如SeekBar的监听事件的接口,你可能只需要onProgressChanged(); 但是你不得不把另外两个方法实现!
但是用了RxBinding,你只需要这样写!
//这里只传递了进度
RxSeekBar.changes(seekbar)
.subscribe(new Action1<Integer>() {
@Override
public void call(Integer integer) {
}
})
3.RxBinding支持对点击事件的多次监听并且实现起来非常简单。RxBinding本身不能做到,但它与RxJava的操作方法结合可以做到,如:publish(), share(), replay()
Button b = (Button) v.findViewById(R.id.button);
Observable<Void> observable= RxView.clicks(b).share();
Subscription s = observable.subscribe(new Action1<Void>() {
@Override
public void call(Void aVoid) {
// do something
}
});
compositeSubscription.add(s);
Subscription s1 = observable.subscribe(new Action1<Void>() {
@Override
public void call(Void aVoid) {
// do something
}
});
compositeSubscription.add(s1);
4.各种View的常用事件,RxBinding都支持!, 还有appcompat-v7 ,design, 等等也都有单独的支持包!
.
要注意的点
RxBinding可能造成内存泄漏,所以最好手动取消订阅!
.
Subscription s1 = observable.subscribe(new Action1<Void>() {
@Override
public void call(Void aVoid) {
// do something
}
});
compositeSubscription.add(s1);
//Acivity退出时 释放
Protected void OnDestory(){
s1.unScribe();
}
或者使用RxLifeCycle, 这个库就是用来解决RxJava带来的内存泄漏!
如何使用readme里也比较清楚了。
地址: https://github.com/trello/RxLifecycle
RxBinding实现分析
RxBinding的实现其实比较简单: 借鉴一句话,就是语法糖,但是这糖真的好吃啊!!!
先说下大概的结构:
1.对用View的各种基础事件如点击事件,拖拽事件都是封装在RxView里的,类似的还有RxViewGroup
2. 对于某个View特有的事件封装在对应名称的类中,如RxTextView(TextWatcher), RxSeekBar, RxToolBar等等
3.对于各种单个参数的或者无参数的事件(如OnClickListener), 都封装为XXXXXOnSubscribe , 比如:ViewClickOnSubscribe
对于多个参数的事件都先把参数封装为xxxxEvent, 如:TextViewAfterTextChangeEvent
然后再封装一个XXXXOnSunscribe<xxxxEvent>, 这就等同于ViewClickOnSubscribe了:
你可能会问,神经啊,为甚非要封装成Event,传递单个参数, 莫急后面你就明白了!
拿个最简单的点击事件做例子简单分析下:
可以看到继承了Observable.OnSubscribe其实就是一个Action1:
然后,在call方法里,检测了当前是否为UI线程,不是的话抛出异常,否则view添加了OnClickListener, onClick调用了onNext();
然后说说这个MainThreadSubscription:
之前写了一篇文章: RxAndroid深入理解 http://www.jianshu.com/p/8292ea39c38e
留下了一个尾巴:MainThreadSubscription
贴上代码:
主要看unsubscribe方法, 这个方法就是取消订阅时做的事,该方法首先判断了是否为UI线程,是的话调用了onUnsubscribe();方法,非UI线程的话,调用了AndroidSchedulers.mainThread():
实际上调用了LooperScheduler的createWorker(), createWorker()实际上创建了一个叫HandlerWorker的类,之前那边文章也讲了,如果看的觉得理不清,看看我之前的那篇文章HandlerWorker其实就是持有一个根据用户传递给LooperScheduler的Looper所创建的Handler, 然后SechduleAction 把这里的action0:
包装成一个Runnable, 让handler发送到所在线程! 从而被执行!
但是因为AndroidSchedulers.mainThread()传递的就是Looper.getMainLooper(),即UI线程的Looper
所以在非UI线程的情况下, onUnsubscribe();方法也只会在UI线程执行!
.
RxAnimation实现
.
这是我自己模仿RxBinding实现的对动画的各种事件的处理! 其实很简单!
地址:https://github.com/niniloveyou/RxJava-learn
.有兴趣的看看!!!
比如我想在渐变动画执行完的时候做些什么! 就可以这样写了!
RxAnimation.onEnd(animation)
.subscribe(new Action1<Animation>() {
@Override
public void call(Animation animation) {
// do something
}
});
或者valueAnimator/ObjectAnimator
//update
RxAnimator.onUpdate(animator)
.subscribe(new Action1<Float>() {
@Override
public void call(Float value) {
//do something
}
});
这波装的可以吧! 可以你就点个赞。