Android心得总结

Retrofit 2.4.0 工作流程源码解析

2019-07-27  本文已影响2人  BzCoder

本文参考 Retrofit分析-漂亮的解耦套路
图片来源 Retrofit分析-漂亮的解耦套路
源码版本:Retrofit2.4.0 Rxjava2 2.2.0

Refrofit流程图

Retrofit原理

我们根据这张流程图来对着源码慢慢来看。一切从左上角开始。

1.retrofit.create(service.class)

  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.adapt(okHttpCall);
          }
        });
  }

这里主要用到了JDK的动态代理功能。实现InvocationHandler接口即可。通过loadServiceMethod()代理生成传入Service的代理类ServiceMethod。下方的OkHttpCall是OKhttp3的封装类。最后通过serviceMethod.adapt(okHttpCall)将okHttpCall设置回serviceMethod中,以便之后在各种CallAdapter中使用。callAdapter是一个适配器,适配成其他平台可以使用的类型,比如转化为Rxjava或者Rxjava2。

    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;
  }

这里回头再看下loadServiceMethod()方法,他设置了缓存池,自身是通过ServiceMethod.Builder()建造者来生成,此方法将收集传入的service方法包含的注解信息以及在Retrofit.Builder()方法中配置的BaseUrl,okHttpClient,Converter,CallAdapter并将其转化为参数设置到result中。此时我们传入的service中所有数据都已经装配完毕了。此时上图中我们已经进行到了图中CallAdapter.adapt。由上述代码我们可知retrofit.create({service}).{service.method}.实际调用的是callAdapter.adapt(call)。

2.CallAdapter.adapt(call)

CallAdapter实现类

完成了以上配置工作,接下来就要开始动手干活了。CallAdapter有四个实现类,以现在的最常用的Rxjava2.2.0 + Retrofit2.4.0模式为例,所以最终调用的是RxJava2CallAdapter中的adapt方法。(当然RxJava2CallAdapter在顶部图片是已经没有了)

 @Override public Object adapt(Call<R> call) {
    Observable<Response<R>> responseObservable = isAsync
        ? new CallEnqueueObservable<>(call)
        : new CallExecuteObservable<>(call);
   ...
  }

上述代码中CallEnqueueObservable与CallExecuteObservable对应Okhttp中的异步请求和同步请求。这里通过RxJava2CallAdapterFactory.create()/createAsync()去设置,本质是改变Okhttp请求方法来控制同步异步,但是现在很多做法是通过Rxjava2去调度使用的时候去调度线程,所以可以看到很多库封装Retrofit是使用RxJava2CallAdapterFactory.create()的。但是我们这里还是着重看下异步请求。

3.CallEnqueueObservable

final class CallEnqueueObservable<T> extends Observable<Response<T>> {
....
  @Override protected void subscribeActual(Observer<? super Response<T>> observer) {
    // Since Call is a one-shot type, clone it for each new observer.
    Call<T> call = originalCall.clone();
    CallCallback<T> callback = new CallCallback<>(call, observer);
    observer.onSubscribe(callback);
    call.enqueue(callback);
  }
private static final class CallCallback<T> implements Disposable, Callback<T> {
....
    CallCallback(Call<?> call, Observer<? super Response<T>> observer) {
      this.call = call;
      this.observer = observer;
    }

    @Override public void onResponse(Call<T> call, Response<T> response) {
      if (call.isCanceled()) return;
      try {
        observer.onNext(response);
        if (!call.isCanceled()) {
          terminated = true;
          observer.onComplete();
        }
      } catch (Throwable t) {
      ....
          }
        }
      }
    }

    @Override public void onFailure(Call<T> call, Throwable t) {
   ....
    }
...
}

CallEnqueueObservable重写了subscribeActual,subscribeActual会在subscribe中调用。其中CallCallback是连接Retrofit,Rxjava2,OKhttp的桥梁,Okhttp产生回调后会传回Retrofit,最终通知Rxjava2。这里也走到了最终网络请求的方法call.enqueue(callback),点进去我们就可以看到熟悉的OKHttp的网络方法。

4.call.enqueue(new okhttp3.Callback()

 call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
        Response<T> response;
        try {
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          callFailure(e);
          return;
        }

        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

      @Override public void onFailure(okhttp3.Call call, IOException e) {
        callFailure(e);
      }

      private void callFailure(Throwable e) {
        try {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }
    });
  }

在call.enqueue中还看到中callback.onResponse(OkHttpCall.this, response)callback.onFailure(OkHttpCall.this, e)此处的callback就是observer.onSubscribe(callback)中设置的callback,就此回到Retrofit的回调。在CallCallback.onResponse中又有observer.onNext(response)最后回到了Rxjava2。至此流程结束。接下来就全部是Rxjava2的事儿了。

5.总结

Retrofit2在灵活解耦方面做的十分精妙,需要多看几次学习学习其中的思想。如果文章中描述有误,欢迎在留言中指出。

上一篇下一篇

猜你喜欢

热点阅读