RxAndroid and Kotlin (Part1)
来源:互联网 发布:unix网络编程2 pdf 编辑:程序博客网 时间:2024/05/21 20:30
原文作者:Ahmed Rizwan
原文链接:RxAndroid and Kotlin (Part1)
译文作者:Dimon
译者语:由于本人水平有限,翻译可能会存在偏差,望大大们谅解。如发现问题,可评论告知,好及时改正~翻译文章只为交流学习,谢谢观看。
文中的
Subscriber
我直接译为观察者了,只是为了方便自己理解,如有不悦,见谅。
我开始关注RxAndroid已经差不多一周时间了。一开始,我并没有真正意义上地理解它...我的意思是:我抓住了它的概念,但是我却不清楚该何时使用它。不过后来看了一些例子以及一些干货文章(链接在文章末)后,我才算了解RxAndroid
!(到了个良好的程度)当时的内心如下:
简而言之,你几乎可以在任何地方使用Rx
,但你不能这样做。你应该明智地揣摩哪儿更适合使用它,因为在某种情况下,Rx
可以提升100倍以上的生产性或者比正常命令性编程更好,而在其他情况下,则是没必要使用它的。
那么以下,我将展示Kotlin
和Java
这两种语言关于Rx
的一些例子。
如果你现在对
Kotlin
不那么熟悉,那么我建议您可以访问以下链接:Official Kotlin Website
Getting Started on Android
Jake Wharton’s Paper on Kotlin
摘要: Kotlin is an awesometacular alternative to Java, that works amazingly well on Android. And oh, it's developed by JetBrains!
P.S.
Kotlin
是没有分号的。:-)
Rx:概念
如果你已经对于Rx
有了很好的概念,那么你可以跳过这一part。否则...请你继续吞了下面的这颗安利!!!
那么什么是Rx呢?(⊙v⊙)蒽...其实就是响应式编程reactive programming
...用简单的话说,响应式编程reactive programming
其实就是一种与观察者模式Observer Pattern
密切相关的编程模式。
其中,由被观察者Observable
调用了观察者Subscriber
的回调方法,就实现了由被观察者Observable
向观察者Subscriber
的事件传递,即观察者模式Observer Pattern
。
Rx
也是函数式编程的一个子集。所以经常被称为Functional Reactive Programming
。因为...作为用户接收的数据,它们可以申请它们的转换序列。(类似于我们在Java8中的对流所做的)
我们甚至可以结合或者说合并不同的流streams
。它就是这么的灵活!所以,现在我们只记得有一堆不同的、我们(观察者Subscriber
)可以从被观察者Observable
中接收的数据。
现在,概念开始有点清晰,让我们回过头来看看RxJava。
在Rx中,观察者subscriber
的三个事件回调方法:
1.onNext(Data)
:从被观察者Observale
中接收数据(相当于 onClick() / onEvent())
2.onError(Exception)
:如果抛出异常,这个方法将被调用
3.onCompleted()
:将在事件队列完结时调用。
RxJava
不仅把每个事件单独处理,还会把它们看做一个队列。RxJava
规定,当不会再有新的onNext()
发出时,需要触发onCompleted()
方法作为标志。
其实这就像Iterables
在Java
里那样。但有所不同的是,Iterables
是pull
型,而Rx中的被观察者们Observales
是push
型,这是被观察者Observable
将数据推到了其观察者subscribers
中。以下是他们之间的比较表格:
另外需要注意的是,Rx本质上是异步的,也就是说观察者
subscribers
不会等待其他观察者subscribers
。他们其实“异步”的过程流。
所以被观察者Observables
推出的数据流给他们的观察者subscribers
,然后观察者subscribers
可以处置这些流(在上面的方法的帮助下)。我们可以通过下面的 Marble Diagrams来更好地了解流:
这些圆圈代表着的是流上的数据对象。箭头代表该数据流动的一个方向,以有序的方式!再看看以下图:
就像我之前提到的,我们可以将类似于map、filter、zip等等使用operators
转变成数据(以及流)。上图表示的是一种简单的映射。所以这一转变后,观察者subscriber
这个流将得到转变后的流,怎么样?酷吧!
我想你现在应该对Rx是如何工作已经有了一个很好的概念,所以现在让我们开始实际操作吧。
- 好,我们要做的第一件事就是打坐。(莫打趣,其实只是想思考代码)
- 然后,创建一个被观察者
Observable
亦不是难事。
这有一些可以创建被观察者Observables
的方式,我只是将其中三个罗列出来:
1.Observable.from()
: 将传入的数组或 Iterable 拆分成具体对象后,依次发送出来。
//KotlinObservable.from(listOf(1, 2, 3, 4, 5))//JavaObservable.from(Arrays.asList(1, 2, 3, 4, 5));//它将会发出以下这些数字 : 1 - 2 - 3 - 4 - 5
String[] words = {"Hello", "Hi", "Aloha"};Observable observable = Observable.from(words);// 将会依次调用:// onNext("Hello");// onNext("Hi");// onNext("Aloha");// onCompleted();
2.Observable.just() :将传入的参数依次发送出来。
Observable observable = Observable.just("Hello", "Hi", "Aloha");// 将会依次调用:// onNext("Hello");// onNext("Hi");// onNext("Aloha");// onCompleted();
3.Observable.create() :创建一个 Observable
,实现OnSubscribe
接口,并告诉被观察者observable
当它被订阅时,OnSubscribe
的call()
方法会自动被调用,将数据发送到观察者subscriber(s)
。
//KotlinObservable.create(object : Observable.OnSubscribe<Int> { override fun call(subscriber: Subscriber<in Int>) { for(i in 1 .. 5) subscriber.onNext(i) subscriber.onCompleted() }})
相同代码的Java版本:
//JavaObservable.create(new Observable.OnSubscribe<Integer>() { @Override public void call(final Subscriber<? super Integer>subscriber) { for (int i = 1; i <= 5; i++) subscriber.onNext(i); subscriber.onCompleted(); }});
上面写的代码就相当于我写了Observable.from()
的例子,但你可以看到,我们可以充分控制发出什么东西、什么时候流可以结束。还可以使用subscribe.onError(e)
发送捕获到的异常。
好了,到了现在,我们需要实现观察者subscriber
。
实现观察者subscriber
在我们已经实现被Observables
之后,我们需要的一个subscriber
!对于安卓而言,订阅一个被Observable
我们首先要告诉observable
有关我们打算订阅和观察的线程。RxAndroid
给我们的Schedulers
,通过它我们可以指定相应的线程。所以,让我们举一个简单的“Hello World”observable
的例子,实现在worker thread
完成订阅,在main thread
上观察。
//KotlinObservable.just("Hello World") .subscribeOn(Schedulers.newThread()) //each subscription is going to be on a new thread. .observeOn(AndroidSchedulers.mainThread())) //observation on the main thread //Now our subscriber! .subscribe(object:Subscriber<String>(){ override fun onCompleted() { //Completed } override fun onError(e: Throwable?) { //TODO : Handle error here } override fun onNext(t: String?) { Log.e("Output",t); } })//JavaObservable.just("Hello World") .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber<String>() { @Override public void onCompleted() { //Completion } @Override public void onError(final Throwable e) { //TODO : Handle error here } @Override public void onNext(final String s) { Log.e("Output",s); } });
你可以在这里得到有关调度与线程的更多信息。
那,它是怎么工作的呢?
当你运行上面那段代码时,它会显示一个日志消息
Output: Hello World!
你看,“订阅”就是如此的简单。你可以点击这里获取更多关于订阅的相关详情。
一个简单的实例:Debounce!!!
好了,你现在知道了如何创建简单的observables
了对不对?~
那么让我们来做我们自己喜欢的RxExamples
~~
我呢~想实现这个:
在这个例子里,我将文本输入到一个EditText
中,并且针对该文本:当我输入时,一个响应将被自动触发,从而打印出我输入的文本。现在这样的反应可能被称为一个API
的调用。所以,如果我触发此要求输入了的每一个字符——这将是一种浪费,因为我只需要知道最后一个输入,这意味着在我停止打字的时候它应该只触发一个call
——也就是在我打字后,静止一秒的说~!
那么该如何才能在non-reactive programming
做到这一点呢?
Non-Reactive Solution
我用一个定时器,并且安排它在afterTextChanged()
方法延时1000毫秒后调用run()
方法。呃,不要忘记了也要在那添加runOnUiThread()
。-_-
其实在概念上,实现起来并不难,但是却会让代码变得非常混乱,在Java
中更是如此。
Java version
//JavaTimer timer = new Timer();final TextView textView = (TextView) findViewById(R.id.textView);final EditText editText = (EditText) findViewById(R.id.editText);editText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(final CharSequence s, int start, int before, int count) { if (timer != null) timer.cancel(); } @Override public void afterTextChanged(final Editable s) { timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { runOnUiThread(new Runnable() { @Override public void run() { textView.setText("Output : " + editText.getText()); } }); } }, 1000); }});
- Kotlin
//Kotlinvar timer: Timer? = Timer()val editTextStop = findViewById(R.id.editText) as EditTexteditTextStop.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) = Unit override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { timer?.cancel() } override fun afterTextChanged(s: Editable) { timer = Timer() timer!!.schedule(object : TimerTask() { override fun run() { runOnUiThread { textView.setText("Output : " + editTextStop.getText()) } } }, 1000) }})
Reactive Solution
反应式的解决方案是一个非常自由的样板。而且只有3个步骤。
1.创建一个observable
2.添加Debounce operator
,1000毫秒(1秒)的延迟
3.订阅它
- 首先是
Java
代码
Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(final Subscriber<? super String> subscriber) { editText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(final CharSequence s, final int start, final int count, final int after) { } @Override public void onTextChanged(final CharSequence s, final int start, final int before, final int count) { subscriber.onNext(s.toString()); } @Override public void afterTextChanged(final Editable s) { } }); } }) .debounce(1000, TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<String>() { @Override public void call(final String s) { textView.setText("Output : " + s); } });
Kotlin
❤
Observable.create(Observable.OnSubscribe<String> { subscriber -> editText.addTextChangedListener(object : TextWatcher { override fun afterTextChanged(s: Editable?) = Unit override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) = subscriber.onNext(s.toString()) }) }).debounce(1000, TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ text -> textView.text = "Output : " + text })
更少的样板——RxBindings
!
我们可以使用RxBindings——这是RxJava
结合了Android
的UI组件的API
。它适用于Java
和Kotlin
!快去使用它吧!!
//Java with Retrolambda and RxBinding RxTextView.afterTextChangeEvents(editText) .debounce(1000,TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread()) .subscribe(tvChangeEvent -> { textView.setText("Output : " + tvChangeEvent.view() .getText()); }); //Kotlin with RxBinding RxTextView.afterTextChangeEvents(editText) .debounce(1000, TimeUnit.MILLISECONDS) .observeOn(AndroidSchedulers.mainThread()) .subscribe { tvChangeEvent -> textView.text = "Output : " + tvChangeEvent.view().text }
正如你所看到的,更少的代码。如果在几个月前看着段代码,我很难在一分钟你弄清楚这是怎么回事。这可真是无价之宝!
下面是一些我推荐的关于Rx的一些资源!我将会继续研究Rx+(kotlin&Java)
和继续完成part2
的,敬请关注!
- Official Rx Page
- Grokking RxJava Series by Dan Lew
- Android Rx, and Kotlin : A case study
- Replace AsyncTasks with Rx
- PhilosophicalHacker Blog on Rx
- Implementing EventBus in Rx
- RxKotlin
作者:Dimon喰
链接:http://www.jianshu.com/p/5a730187c8ff
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
- RxAndroid and Kotlin (Part1)
- 【译文】RxAndroid and Kotlin (Part1)
- RxAndroid--Part1
- Kotlin入门 + RxAndroid+Retrofit2
- 【译文】Kotlin : Retrofit + RxAndroid + Realm
- 用Kotlin写响应式编程RxAndroid
- Heap And Stack -- Part1
- java Set and List part1
- Class and object initialization-part1
- RxAndroid
- RxAndroid
- RxAndroid
- RxAndroid
- RXAndroid
- RxAndroid
- RXAndroid
- Android and Kotlin
- chapter11 separate Compilition and Namespaces(part1)
- QGC的MainToolBarIndicator
- 1019(树状数组的区间更新,区间求和)
- U3D中模型后面加载2D背景(多相机分层显示 )
- HBase(1)-HBase的分布式安装
- JAVA获取远程文件
- RxAndroid and Kotlin (Part1)
- vmvar安装mac系统全过程
- sql如何同时查询多张表(union关键字)
- GBK和UTF-8的区别
- 【 js 基础 】【 源码学习 】backbone 源码阅读(三)
- chrome加载本地js
- pom.xml出现web.xml is missing and <failOnMissingWebXml> is set to true解决方案
- 浏览器打开一个网页时都发生了什么
- windows安装程序无法将windows配置为在此计算机