RxJava provides a lot of operators for transformation, such as map and flatMap. Generally, when we use them, we usually understand the meaning of each operator by looking at the official document. However, I feel that it is ok to use them by looking at the official document, but there is always a little bit of trivial meaning. So I have to go to RxJava source to see what it is, do know.

Let’s start with a relatively simple Map

Map

Authoritative definition: Transform the items emitted by an Observable by applying a function to each item

Apply a function to convert all emitted items

Official illustration:

Here we summarize:

  • The map conversion is one-to-one, sending a few data and then a few after the conversion
  • Map transformations can change the type of data emitted

This raises the question, map calls the function we provide for conversion, so when is this function called? In which thread is it called? (This makes sense for us to use map in real projects, knowing that the thread in which the code is executed is necessary)

Nonsense not to say, into the source

The Map source

Observable class is the face of RxJava, where almost all converters are defined. See Map method definitions directly

As you can see, the Function class takes two arguments, the first is the original data type, the second is the converted data type, and finally returns the ObservableMap class. ObservableMap (ObservableMap) ObservableMap (ObservableMap) ObservableMap (ObservableMap) ObservableMap (ObservableMap) ObservableMap overwrites the subscribeActual hook method that subscribeActual is an important hook method

The subscribe method calls the subscribe method of the decorated Observable, passing in a MapObserver object. Observer classes are familiar, but we’ll focus on the onNext method

The code is also very simple, the red box marks where the Mapper transform function is called, resulting in the transformed object V, which is passed to the onNext method of the decorated Observer. At this point, a map transformation of the data is completed. The implementation of the source code is very simple, after we understand the implementation of the source code, the idea will be more clear, write code will be more sure.

Now to answer the question we raised earlier, when is Function called? In which thread is it called? Function is called in the onNext method of ObserverMap, and the thread that is called is called in the Observer method. So if the ObserverOn method is called before the map, the listener thread is called in the Observer thread. If you don’t set ObserverOn but set the SubscribeOn method to set the emitting thread, that’s the emitting thread, or create the thread in the Observable if SubscribeOn is not set.

To this Map on the introduction of the end, the next is Map FlatMap, a good brother, call logic a little bit more complex, see the official patience -. –

###FlatMap

Official definition: transform the items emitted by an Observable into Observables, then flatten the emissions from those into a single Observable

Apply a function to convert all emitted items from one Observable to multiple Observables, and tile all emitted data into one Observable

Official illustration:

Here we summarize:

  • Flatmap conversions are one-to-many (one-to-one is also supported, of course), where several data are transmitted and more data can be converted
  • The flatMap transformation can also change the data type emitted
  • The converted data of the flatMap will still be sent to our Observer one by one for receiving (just as the data is transmitted by one Observable, in fact, it is transmitted by multiple Observables and then merged).

A question is raised here. FlatMap converts original Observables into multiple Observables to transmit data. Will the transmitted data be transmitted in strict order and received by the Observer?

I’ll leave it here and go into the source code

FlatMap source

The FlatMap operator involves a bit more code, but there are rules to follow. In the same way, the source code author provides multiple method overloads to facilitate developers to call the flatMap in Observable class. The most commonly used method definitions are as follows

The method that gets called is

Much like map, we’ll go directly to the ObservableFlatMap class and look again at its subscribeActual method implementation

As you can see, the Observer that it decorates is MergeObserver. Let’s continue with MergeObserver’s onNext method

Since the maxConcurrency size of the default flatmap is integer-. MAX_VALUE, we will call subscribeInner(p). Note that the mapper method is called. P is the Observable generated by the Function we passed in, so let’s keep going

Usually, the Observable generated by the Function we pass in is not of Callable type, so the InnerObserver is passed to Observable P. If you find the culprit, look directly at the implementation of its onNext method.

FunsionMode defaults to None. The first if logic will eventually call the MergeObserable tryEmit method above

MergeObserver inherits AtomicInteger, so the tryEmit method uses AtomicInteger synchronization, so only one value is emitted by the Actual Observer at the same time. AtomicInteger CAS locks can only ensure atomicity of operations, but not preemption order, so the final data emission order is not fixed (the data emitted by the same Observable is ordered).

The drainLoop method loops the data in the drainLoop if it doesn’t get a lock, and then streams it.

Map and FlatMap two operators of the source code on the resolution to here, the level is limited, there are wrong, but also hope big guy not hesitate to give advice.