Ali P7 mobile Internet architect, Advanced Video (Daily update) for free learning, please click: https://space.bilibili.com/474380680
Convert
RxJava provides support for transforming the sequence of events, which is one of its core functions, but also most people say, "RxJava really handy," the biggest reason. The so-called conversion, the sequence of events is an object or the entire sequence of processing, converted to a different event or sequence of events. He said always difficult to understand the concept of fuzzy, look API.
1) API
First, a look at map()
an example:
Here there is a named Func1
class. It Action1
is very similar, is RxJava an interface, a method for packaging containing a parameter. Func1
And the Action
difference is that the Func1
packaging is a method that returns a value. Further, and ActionX
as FuncX
there are a plurality of process parameters for the different number. FuncX
And ActionX
differences in FuncX
the packaging method of the return value is.
We can see, map()
method parameter String
object into a Bitmap
subject upon return, while after map()
the method, also by the type of event parameters String
into the Bitmap
. This direct conversion object and returns, is the most common and most easily understood transformations. But RxJava transform much more than this, it is not only possible, but also for the entire event queue for the event object, which makes RxJava very flexible. I have listed a few common transformation:
-
map()
: Direct conversion event object, the specific function above has been introduced. It is most commonly used RxJava transformation.map()
Schematic:map () schematic -
flatMap()
: This is a very useful, but very difficult to understand the transformation, so I decided to spend more space to introduce it. First, assuming that such a need: Suppose there is a data structure "Student", now need to print out the name of a group of students. Implementation is very simple:
Very simple. Then another hypothesis: the name of each student in all courses required for repair if you want to print it out? (The difference between the demand that each student has only one name, but there is more than one course.) First of all can be achieved:
It is still very simple. So if I do not want to Subscriber
use a for loop, but to Subscriber
direct incoming individual Course
objects it (which is important for code reuse)? With map()
apparently not enough, because map()
one to one conversion, but I now request is transforming many. Then how can the Student converted into a more Course it?
This time, we need to use flatMap()
the:
As can be seen from the above code, flatMap()
and map()
return it is another object of the passed parameters after conversion: a same point. Note, however, and map()
the difference is that flatMap()
in return is Observable
the object, and the Observable
object is not being sent directly to the Subscriber
callback method. flatMap()
The principle is this: 1. Create a passed in the event object Observable
. Object; 2 does not send this Observable
. But to activate it, then it starts sending events; create a 3 out of every Observable
event that is sent, were import the same Observable
, and this Observable
is responsible for these events will be unified to the Subscriber
callback method. These three steps, the event split into two, through a newly created group Observable
distributed down after the initial object "pave" a unified path. And this "pave" is the flatMap()
so-called flat.
flatMap()
schematic diagram:
Extensions: since nested Observable
added asynchronous code, flatMap()
also commonly used for nested asynchronous operation, such as nested network requests. Sample Code (Retrofit + RxJava):
Traditional nested Callback request requires use nested achieved. Through flatMap()
, the write request can be nested in one strand, thereby maintaining clarity of program logic.
throttleFirst()
: Discard new events within a certain time interval after each trigger event. It is often used as a de-jitter filter, such as a button click listener:RxView.clickEvents(button) // RxBinding 代码,后面的文章有解释 .throttleFirst(500, TimeUnit.MILLISECONDS) // 设置防抖间隔为 500ms .subscribe(subscriber);
my mother no longer afraid of my tremor user interface points to open two repeat it.
In addition, RxJava also provides many convenient ways to achieve transformation sequence of events, there is not one by one example.
2) the principle of transformation: lift ()
这些变换虽然功能各有不同,但实质上都是针对事件序列的处理和再发送。而在 RxJava 的内部,它们是基于同一个基础的变换方法: lift(Operator)
。首先看一下 lift()
的内部实现(仅核心代码):
这段代码很有意思:它生成了一个新的 Observable
并返回,而且创建新 Observable
所用的参数 OnSubscribe
的回调方法 call()
中的实现竟然看起来和前面讲过的 Observable.subscribe()
一样!然而它们并不一样哟~不一样的地方关键就在于第二行 onSubscribe.call(subscriber)
中的 onSubscribe
所指代的对象不同(高能预警:接下来的几句话可能会导致身体的严重不适)——
subscribe()
中这句话的onSubscribe
指的是Observable
中的onSubscribe
对象,这个没有问题,但是lift()
之后的情况就复杂了点。- 当含有
lift()
时:
1.lift()
创建了一个Observable
后,加上之前的原始Observable
,已经有两个Observable
了;
2.而同样地,新Observable
里的新OnSubscribe
加上之前的原始Observable
中的原始OnSubscribe
,也就有了两个OnSubscribe
;
3.当用户调用经过lift()
后的Observable
的subscribe()
的时候,使用的是lift()
所返回的新的Observable
,于是它所触发的onSubscribe.call(subscriber)
,也是用的新Observable
中的新OnSubscribe
,即在lift()
中生成的那个OnSubscribe
;
4.而这个新OnSubscribe
的call()
方法中的onSubscribe
,就是指的原始Observable
中的原始OnSubscribe
,在这个call()
方法里,新OnSubscribe
利用operator.call(subscriber)
生成了一个新的Subscriber
(Operator
就是在这里,通过自己的call()
方法将新Subscriber
和原始Subscriber
进行关联,并插入自己的『变换』代码以实现变换),然后利用这个新Subscriber
向原始Observable
进行订阅。
这样就实现了lift()
过程,有点像一种代理机制,通过事件拦截和处理实现事件序列的变换。
精简掉细节的话,也可以这么说:在 Observable
执行了 lift(Operator)
方法之后,会返回一个新的 Observable
,这个新的 Observable
会像一个代理一样,负责接收原始的 Observable
发出的事件,并在处理后发送给 Subscriber
。
如果你更喜欢具象思维,可以看图:
或者可以看动图:
两次和多次的 lift()
同理,如下图:
举一个具体的 Operator
的实现。下面这是一个将事件中的 Integer
对象转换成 String
的例子,仅供参考:
讲述
lift()
的原理只是为了让你更好地了解 RxJava ,从而可以更好地使用它。然而不管你是否理解了lift()
的原理,RxJava 都不建议开发者自定义Operator
来直接使用lift()
,而是建议尽量使用已有的lift()
包装方法(如map()
flatMap()
等)进行组合来实现需求,因为直接使用 lift() 非常容易发生一些难以发现的错误。
3) compose: 对 Observable 整体的变换
除了 lift()
之外, Observable
还有一个变换方法叫做 compose(Transformer)
。它和 lift()
的区别在于, lift()
是针对事件项和事件序列的,而 compose()
是针对 Observable
自身进行变换。举个例子,假设在程序中有多个 Observable
,并且他们都需要应用一组相同的 lift()
变换。你可以这么写:
你觉得这样太不软件工程了,于是你改成了这样:
Readability, maintainability have increased. But Observable
be wrapped up one way, this way for Observale
flexibility seems to add a point so limited. How to do? This time, it should compose()
be solved:
Thus as above, using the compose()
method, Observable
may be utilized incoming Transformer
object call
method directly process itself, it need not be in the interior of the method.
Original link https://gank.io/post/560e15be2dca930e00da1083#toc_17
Ali P7 mobile Internet architect, Advanced Video (Daily update) for free learning, please click: https://space.bilibili.com/474380680