[Android] RxJava source code flow analysis

One, RxJava introduction

Rxjava is a third-party library that will be used in many projects. In the project, Rxjava+retrofit is useful for project development, so understanding the principle of this third-party library can solve many hidden problems.

2. Process analysis

Insert picture description here
Insert picture description here
Insert picture description here
Eventually a chain of observers will be formed, and each observer object has its own thread Schedulers to switch threads.
OkHttpCall encapsulates okhttp3 related operations.
Analyze the process in 5 steps:
Step 1: Set RxJava2CallAdapter
in retrofit.addCallApdapterFactory(RxJava2CallAdapterFactory.create()), and add RxJava2CallAdapterFactory to the variable private final List<CallAdapter.Factory> adapterFactories = new ArrayList<>() in retrofit ;
In, the generation adaptation class RxJava2CallAdapter
will be used later. This class will call adapt (Call call) to generate the Observable object of the observable . This is a typical bridge mode.
Step 2: In the dynamic proxy object
create function of the dynamic proxy object, the dynamic proxy class must implement the InvocationHandler interface. When we call a method through the proxy object, the call of this method will be forwarded to the interface of InvocationHandler invoke method to make the call. Let's take a look at the only method invoke method of the InvocationHandler interface, that is, when service.getSearchBook() is called later, it will go to this invoke method.

public <T> T create(final Class<T> service) {
    
    
  Utils.validateServiceInterface(service);
  if (validateEagerly) {
    
    
    eagerlyValidateMethods(service);
  }
  return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] {
    
     service },
      new InvocationHandler() {
    
    
        private final Platform platform = Platform.get();

        @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
            throws Throwable {
    
    
          // If the method is a method from Object then defer to normal invocation.
          if (method.getDeclaringClass() == Object.class) {
    
    
            return method.invoke(this, args);
          }
          if (platform.isDefaultMethod(method)) {
    
    
            return platform.invokeDefaultMethod(method, service, proxy, args);
          }
          ServiceMethod<Object, Object> serviceMethod =
              (ServiceMethod<Object, Object>) loadServiceMethod(method);
          OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
          return serviceMethod.callAdapter.adapt(okHttpCall);
        }
      });
}
ServiceMethod<?, ?> loadServiceMethod(Method method) {
    
    
  ServiceMethod<?, ?> result = serviceMethodCache.get(method);
  if (result != null) return result;

  synchronized (serviceMethodCache) {
    
    
    result = serviceMethodCache.get(method);
    if (result == null) {
    
    
      result = new ServiceMethod.Builder<>(this, method).build();
      serviceMethodCache.put(method, result);
    }
  }
  return result;
}

Among them, SerivceMethod.callAdapter.adapt(okHttpCall), generation process: In
ServiceMethod.Builder().build(), call retroift.callAdatper() to generate callAdapter object.
In retrofit, callAdapter calls nextCallAdapter again. In it, the RxJava2CallAdapterFactory object is taken out of the adapterFactories variable, and get() is called to generate RxJava2CallAdapter.
Finally, serviceMethod.callAdapter.adapt(okHttpCall) will go to the RxJava2CallAdapter.adapt function.
In the RxJava2CallAdapter function:

@Override public <R> Object adapt(Call<R> call) {
    
    
  Observable<Response<R>> responseObservable = new CallObservable<>(call);
  Observable<?> observable;
  if (isResult) {
    
    
    observable = new ResultObservable<>(responseObservable);
  } else if (isBody) {
    
    
    observable = new BodyObservable<>(responseObservable);
  } else {
    
    
    observable = responseObservable;
  }
  if (scheduler != null) {
    
    
    observable = observable.subscribeOn(scheduler);
  }
  if (isFlowable) {
    
    
    return observable.toFlowable(BackpressureStrategy.LATEST);
  }
  if (isSingle) {
    
    
    return observable.singleOrError();
  }
  if (isMaybe) {
    
    
    return observable.singleElement();
  }
  if (isCompletable) {
    
    
    return observable.ignoreElements();
  }
  return observable;
}

Observable will be generated BodyObservable<>(responseObservable); where Observable<Response> responseObservable = new CallObservable<>(call); that is, the variable Observable<Response> upstream of the BodyObservable,
so the object generated in the second step is the
third step of the BodyObservable : Generate ObservableSubscribeOn
observable.subscribeOn(Schedulers.io())

public final Observable<T> subscribeOn(Scheduler scheduler) {
    
    
    ObjectHelper.requireNonNull(scheduler, "scheduler is null");
    return RxJavaPlugins.onAssembly(new ObservableSubscribeOn<T>(this, scheduler));
}

Put BodyObservable and IoScheduler in ObservableSubscribeOn,
where ObservableSource source is BodyObservable

Step 4: Generate ObservableObserveOn
observeOn(AndroidSchedulers.mainThread())

public final Observable<T> observeOn(Scheduler scheduler, boolean delayError, int bufferSize) {
    
    
    ObjectHelper.requireNonNull(scheduler, "scheduler is null");
    ObjectHelper.verifyPositive(bufferSize, "bufferSize");
    return RxJavaPlugins.onAssembly(new ObservableObserveOn<T>(this, scheduler, delayError, bufferSize));
}

Put ObservableSubscribeOn and HandlerScheduler
into the observable ObservableObserveOn, where ObservableSource source is an ObservableSubscribeOn object, forming a responsibility chain mode of the observable, corresponding to each Scheduler to realize the switch between threads, and the Disposable interface, to realize interrupts, etc.

Step 5: Create an observer, and connect to the observed
subscribe(observer)
through the subscriber ; this observer is an observer, and starts processing each event through subscribe.

Guess you like

Origin blog.csdn.net/sinat_36955332/article/details/108511832