Android学习日记

Android日记之Retrofit源码解析

2019-10-19  本文已影响0人  居居居居居居x

前言

别问我为啥先写Retrofit的源码解析而不是okhttp的源码解析,主要是最近这几次面试Retrofit被问到的比例相当的大,所以就先写Retrofit的(其实主要是okhttp在项目上已经用上了,面试官也就懒得问了-_-||),我们老样子,从怎么使用这个框架的地方开始入手源码,Retrofit的使用方法可以看Android日记之Retrofit初探,这里的Retrofit版本是2.5。

Retrofit的构建

Retrofit的Builder()方法

public static final class Builder {
    private final Platform platform;
    private @Nullable okhttp3.Call.Factory callFactory;
    private @Nullable HttpUrl baseUrl;
    private final List<Converter.Factory> converterFactories = new ArrayList<>();
    private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();
    private @Nullable Executor callbackExecutor;
    private boolean validateEagerly;

    Builder(Platform platform) {
      this.platform = platform;
    }

    public Builder() {
      this(Platform.get());
    }
    
    ......
}
class Platform {
  private static final Platform PLATFORM = findPlatform();

  static Platform get() {
    return PLATFORM;
  }

  private static Platform findPlatform() {
    try {
      Class.forName("android.os.Build");
      if (Build.VERSION.SDK_INT != 0) {
        return new Android();
      }
    } catch (ClassNotFoundException ignored) {
    }
    try {
      Class.forName("java.util.Optional");
      return new Java8();
    } catch (ClassNotFoundException ignored) {
    }
    return new Platform();
  }
  
  ......
}

里面主要多了一个Platform,它其实是一个很重要的东西,主要是调用了Platform的get()方法来进行赋值,然后调用里面的findPlatform()方法,这里面主要就是看你是哪个平台的,通过Class.forName来查找指定的类,然后返回一个Android对象(在Android使用肯定是这个的啦),至于这个Android里面主要干了什么,看了下源码,只知道是跟Retrofit要构建的变量Executor有关,看了下其他论坛的讲解,迷迷糊糊的,还是看不懂,以后再看-_-||。

Retrofit的build()方法

//创建Retrfit
Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://wanandroid.com/wxarticle/chapters/json/")
        .addConverterFactory(GsonConverterFactory.create())
        .build();

//build方法源码
public Retrofit build() {
    //这里说明一定需要baseUrl。
    throw new IllegalStateException("Base URL required.");
    }

    //这里判断如果没有callFactory的话,就会创建一个OkHttpClient()。
    okhttp3.Call.Factory callFactory = this.callFactory;
    if (callFactory == null) {
    callFactory = new OkHttpClient();
    }

    //也是一样,如果没有callbackExecutor,就会设置成默认配置defaultCallbackExecutor。
    Executor callbackExecutor = this.callbackExecutor;
    if (callbackExecutor == null) {
    callbackExecutor = platform.defaultCallbackExecutor();
    }
    
    //这里说明会把defaultCallAdapterFactories配置添加到List里面去
    // Make a defensive copy of the adapters and add the default Call adapter.
    List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
    callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));

    // Make a defensive copy of the converters.
    List<Converter.Factory> converterFactories = new ArrayList<>(
      1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());

    // Add the built-in converter factory first. This prevents overriding its behavior but also
    // ensures correct behavior when using converters that consume all types.
    converterFactories.add(new BuiltInConverters());
    converterFactories.addAll(this.converterFactories);
    converterFactories.addAll(platform.defaultConverterFactories());
    
    //然后返回了一个Retrofit对象。
    return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
      unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}

build()方法里可以看出,其实就是创建了一个OkHttpClient的对象,然后进行一系列的配置然后返回一个Retrofit的对象,这里是默认创建一个Okhttp的对象的,这也就代表你也可以外部创建一个Okhttp的对象然后进行传入,比如:

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://wanandroid.com/wxarticle/chapters/json/")
    .addConverterFactory(GsonConverterFactory.create())
    //这里传入外部创建的okhttp对象
    .client(new OkHttpClient())
    .build();

创建网络接口的实例

 //用Retrofit创建接口实例对象
ApiService apiService = retrofit.create(ApiService.class);

//create()源码
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();
          private final Object[] emptyArgs = new Object[0];

          @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);
            }
            return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
          }
        });
}

ServiceMethod<?> loadServiceMethod(Method method) {
    ServiceMethod<?> result = serviceMethodCache.get(method);
    
    //这里用到了单例模式
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = ServiceMethod.parseAnnotations(this, method);
        serviceMethodCache.put(method, result);
      }
    }
    return result;
}

然后经过Retrofit的create创建源码,这是一个非常重要的方法,它是会返回一个泛型T,这里运用了Java的动态代理,也就是Proxy.newProxyInstance()这里调用,然后调用了InvocationHandler()invoke()方法,这里Invoke()方法回向江method转换成ServiceMethod对象,然后传入到构造方法中,最后返回一个Call对象,这里面也用到了双重检查的单例模式,这就代表ServiceMethod只会被创建一次,然后我们重点来看看ServiceMethod是什么样的。
这里需要注意的是Retrofit2.5之前是通过构建者模式进行创建ServiceMethod的,2.5是使用ServiceMethod.parseAnnotations()来进行创建.

abstract class ServiceMethod<T> {
  static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

    Type returnType = method.getGenericReturnType();
    if (Utils.hasUnresolvableType(returnType)) {
      throw methodError(method,
          "Method return type must not include a type variable or wildcard: %s", returnType);
    }
    if (returnType == void.class) {
      throw methodError(method, "Service methods cannot return void.");
    }

    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

  abstract T invoke(Object[] args);
}

这里你会发现它是一个抽象类,这就需要找它的子类的,它的子类是HttpServiceMethod,如下:

private HttpServiceMethod(RequestFactory requestFactory, okhttp3.Call.Factory callFactory,
  CallAdapter<ResponseT, ReturnT> callAdapter,
  Converter<ResponseBody, ResponseT> responseConverter) {
this.requestFactory = requestFactory;
this.callFactory = callFactory;
this.callAdapter = callAdapter;
this.responseConverter = responseConverter;
}

@Override ReturnT invoke(Object[] args) {
return callAdapter.adapt(
    new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));
}

看到这里,其实也差不多明白了,这里创建了一个HttpServiceMethod对象,然后在Retrofit的create()的方法中调用了invoke()方法,返回了一个Call对象,就是我最初刚刚开始说的那个返回,主要是通过callAdapter.adapt()返回,allAdapter.adapt()方法就是将OkHttpCall对象转换成其他平台能用的Call对象,比如:RxJava。这里返回的是OkHttpCall的对象,该类是Retrofit中定义的,是对Okhttp中的Call对象的封装。

Retrofit的异步操作

@Override 
public void enqueue(final Callback<T> callback) {
  checkNotNull(callback, "callback == null");

  delegate.enqueue(new Callback<T>() {
    @Override public void onResponse(Call<T> call, final Response<T> response) {
      // 回调后 利用 MainThreadExecutor 中的 Handler 切换到主线程中去。
      callbackExecutor.execute(new Runnable() {
        @Override public void run() {
          if (delegate.isCanceled()) {
            // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
            callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
          } else {
            callback.onResponse(ExecutorCallbackCall.this, response);
          }
        }
      });
    }

    @Override public void onFailure(Call<T> call, final Throwable t) {
      callbackExecutor.execute(new Runnable() {
        @Override public void run() {
          callback.onFailure(ExecutorCallbackCall.this, t);
        }
      });
    }
  });
}

其实在异步操作这里主要是看它是怎么切换线程的,这里面有一个delegate,就是从这里进行网络请求的,它是一个OkHttpCall,具体的Call请求是交给okhttp来完成的,完成后通过主线程的Handler来切换到主线程中去,具体的网络请求,会写一篇okhttp的源码解析来继续。

参考

上一篇下一篇

猜你喜欢

热点阅读