【RxJava Demo分析】(三)buffer操作符、RxBinding库
2016-03-05 17:11
615 查看
BufferDemoFragment
我们看一下这个原作者的注释:This is a demonstration of the
bufferObservable.
The buffer observable allows taps to be collected only within a time span. So taps outside the
2s limit imposed by buffer will get accumulated in the next log statement.
简而言之,这个buffer Observable可以让你在一个时间段内,计算你点击的次数(或者其他)。
照旧我们看一下所用到的RxJava代码:
private Subscription _subscription; @Override public void onStart() { super.onStart(); _subscription = _getBufferedSubscription(); } @Override public void onPause() { super.onPause(); _subscription.unsubscribe(); } // Main Rx entities private Subscription _getBufferedSubscription() { return RxView.clickEvents(_tapBtn) //RxView .map(new Func1<ViewClickEvent, Integer>() { @Override public Integer call(ViewClickEvent onClickEvent) { Timber.d("--------- GOT A TAP"); _log("GOT A TAP"); return 1; } }) .buffer(2, TimeUnit.SECONDS) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<List<Integer>>() { //一些处理 }); }
从这个例子中我们可以看到两个知识点:buffer操作符、RxBinding库
1.buffer
概括:定期收集Observable的数据放进一个数据包裹,然后发射这些数据包裹,而不是一次发射一个值。我们看看buffer有多少个重载方法:
可见这是一个强大的操作符。
我们举几个典型的来看。
1.带有timespan参数的方法
我们例子中就是使用了带有timespan的方法。buffer(long timespan,TimeUnit unit)
在2s内收集点击的次数。
他还有一个方法:
buffer(long timespan,TimeUnit unit,int count)
第三个参数是限定你在这段时间内,最大是多少。 如果放在本例中的话,就是规定点击次数上限。
2.buffer(int count)、buffer(int count,int skip)
List<String> list = new ArrayList<String>(); list.add("1"); list.add("2"); list.add("3"); list.add("4"); list.add("5"); list.add("6"); Observable.from(list).buffer(2).subscribe(new Action1<List<String>>() { @Override public void call(List<String> arg0) { System.out.println(arg0); } });
我们可以看到输出为:
[1, 2]
[3, 4]
[5, 6]
两两一组~
那么我们就可以猜测一下buffer(2,2)会是什么?
Observable.from(list).buffer(2,2).subscribe(new Action1<List<String>>() { @Override public void call(List<String> arg0) { System.out.println(arg0); } });
输出还是一样:
[1, 2]
[3, 4]
[5, 6]
我们看看两个方法的源代码:
public final Observable<List<T>> buffer(int count) { return buffer(count, count); } public final Observable<List<T>> buffer(int count, int skip) { return lift(new OperatorBufferWithSize<T>(count, skip)); }
发现 buffer(2)就是buffer(2,2)~
再举个例子:buffer(2,3)
输出:
[1, 2]
[4, 5]
所以能总结出:第二个参数就是用来指定 每次分完组之后 从哪一位开始算起~
如果还不明白你看看这个例子,比如list中有1-8的数字,那么buffer(2,4)答案是什么呢?
[1, 2]
[5, 6]
如果答对了,说明你就真的懂了
3.其他的方法
其他的方法呢,我也不太了解,也没有用过。 看文档也不是特别懂,这里就不展开讲了~有兴趣的同学可以看看这里:ReactiveX文档中文翻译-Buffer
2.RxBinding
RxBinding库是大名鼎鼎JakeWharton大神的又一力作。如果没有听过真的是要好好去学习膜拜一下,目前他流行库有:ButterKnife、NineOldAndroids等,而且他还是Square的工程师,Square也有大量的开源库,如OkHttp等。
他可以说是Android开发界最出名的大神了。
RxBinding主要是将View和RxJava绑定起来,使得View可以用RxJava的API来处理点击事件等等操作。
像我们在为控件实现点击事件的时候,我们都是findViewById然后setOnclickListener再处理时间,而经过RxBinding的处理,我们只要这样:
RxView.clickEvents(btn).subscribe(new Observer<ViewClickEvent>() { @Override public void onCompleted() { //不会回调这里 } @Override public void onError(Throwable e) { } @Override public void onNext(ViewClickEvent viewClickEvent) { //进行事件处理 } });
是不是感觉碉堡了!
然而这只是RxBinding的冰山一角。 比如我们有时候希望用户点击了这个按钮之后。(网络请求) ,在一段时间内再次点击我们就可以写:
RxView.clickEvents(button) .throttleFirst(500, TimeUnit.MILLISECONDS)//500ms内不得点击 .subscribe(...);
是不是又碉堡了!
如此优雅简洁的代码,简直是开发神器。
结束
1.小结
实际上我觉得buffer是一个很难使用的操作符,感觉除了点击Button来计算用户点击次数之外,我确实没有想到有什么场景能够使用! 所以说RxJava的痛苦在于例子实在很难想出来啊! 希望有想到应用场景的童鞋能在楼下留言~RxBinding是一个极其强大的View相关的库,如果我们学习了RxJava并打算用在实际开发中,那么学习RxBinding更是如虎添翼。 但我也处于RxJava的学习阶段,所以上面就没有展开RxBinding。 希望学习完RxJava之后,有机会给大家带来RxBinding的讲解
2.附录:完整源代码
public class BufferDemoFragment extends BaseFragment { @Bind(R.id.list_threading_log) ListView _logsList; @Bind(R.id.btn_start_operation) Button _tapBtn; private LogAdapter _adapter; private List<String> _logs; private Subscription _subscription; @Override public void onStart() { super.onStart(); _subscription = _getBufferedSubscription(); } @Override public void onPause() { super.onPause(); _subscription.unsubscribe(); } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); _setupLogger(); } @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View layout = inflater.inflate(R.layout.fragment_buffer, container, false); ButterKnife.bind(this, layout); return layout; } @Override public void onDestroyView() { super.onDestroyView(); ButterKnife.unbind(this); } // ----------------------------------------------------------------------------------- // Main Rx entities private Subscription _getBufferedSubscription() { return RxView.clickEvents(_tapBtn) .map(new Func1<ViewClickEvent, Integer>() { @Override public Integer call(ViewClickEvent onClickEvent) { Timber.d("--------- GOT A TAP"); _log("GOT A TAP"); return 1; } }) .buffer(2, TimeUnit.SECONDS) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<List<Integer>>() { @Override public void onCompleted() { // fyi: you'll never reach here Timber.d("----- onCompleted"); } @Override public void onError(Throwable e) { Timber.e(e, "--------- Woops on error!"); _log("Dang error! check your logs"); } @Override public void onNext(List<Integer> integers) { Timber.d("--------- onNext"); if (integers.size() > 0) { _log(String.format("%d taps", integers.size())); } else { Timber.d("--------- No taps received "); } } }); } // ----------------------------------------------------------------------------------- // Methods that help wiring up the example (irrelevant to RxJava) private void _setupLogger() { _logs = new ArrayList<>(); _adapter = new LogAdapter(getActivity(), new ArrayList<String>()); _logsList.setAdapter(_adapter); } private void _log(String logMsg) { if (_isCurrentlyOnMainThread()) { _logs.add(0, logMsg + " (main thread) "); _adapter.clear(); _adapter.addAll(_logs); } else { _logs.add(0, logMsg + " (NOT main thread) "); // You can only do below stuff on main thread. new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { _adapter.clear(); _adapter.addAll(_logs); } }); } } private boolean _isCurrentlyOnMainThread() { return Looper.myLooper() == Looper.getMainLooper(); } }
-Hans 2016.3.5 17:10
相关文章推荐
- 学习笔记--原生JS
- Poj2746-Housewife Wind 树链剖分入门(边权)
- 获取url上某个参数的值
- bootstrap学习笔记之一
- JS面向对象组件(五) -- 复制对象(拷贝继承)
- js中constructor的作用
- 在AngularJS框架中处理数据建模的方式解析
- 什么样的前端框架才是一个好框架
- 感受HTML5 Audio API带来的视听盛宴
- 整理六百篇web前端知识混总
- 前端学习总结(八)NodeJS——前端工程师通向后端的里程碑
- 前端学习总结(七)Angular.js——以数据交互为核心的前端框架
- JS面向对象组件(四) -- 面向对象的继承
- 前端学习总结(六)Bootstrap
- 前端学习总结(四)jQuery
- PL/SQL database character set(AL32UTF8) and Client character set(ZHS16GBK) are different
- 简单讲解AngularJS的Routing路由的定义与使用
- Webpack入门指迷
- JavaScript常用代码(不定时更新)
- JS操作cookie