Retrofit源碼分析之一

Retrofit 請求網絡

實際上是使用 Retrofit 接口層封裝請求參數、Header、Url 等信息,之後由 OkHttp完成後續的請求操作,在服務端返回數據之後,OkHttp 將原始的結果交給 Retrofit,後者根據用戶的需求對結果進行解析的過程。Retrofit的大概原理過程如下:

  1. Retrofit 將 Http請求 抽象 成 Java接口
  2. 在接口裏用 註解 描述和配置 網絡請求參數
  3. 用動態代理 的方式,動態將網絡請求接口的註解 解析 成HTTP請求
  4. 最後執行HTTP請求

先看調用方式:

1、Retrofit之kotlin使用方式

  1. 1、創建一個api服務管理類
/**
 * Api管理工具類,通過該類創建相應的api-service類
 */
object ApiServiceManager {

    private val gson = GsonBuilder().registerTypeAdapter(Date::class.java, JsonDeserializer<Date> { json, _, _ -> Date(json.asJsonPrimitive.asLong) }).create()

    private val mRetrofit: Retrofit = Retrofit.Builder()
            .baseUrl(RequestDomainConfig.getRequestDefault())
            .client(HttpClientManager.mOkHttpClient)//OKHTTP網絡請求
            .addConverterFactory(GsonConverterFactory.create(gson))//添加json解析器
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())//添加RxJava轉換器
            .build()

    fun <T> create(service: Class<T>): T = mRetrofit.create(service)
}
  1. 2、創建一個服務接口類,供retrofit解析註解
interface ApiUserService {
  
    //用戶登錄
    @POST("userAuth.login")
    fun loginByAccount(@Body httpRequest: HttpRequest): Observable<UserInfoVo>
  1. 3、創建接口調用類(真正調用接口)
object ApiUser {
    private val sService = ApiServiceManager.create(ApiUserService::class.java)


 /**
     * 用戶登錄
     */
    fun <E> loginByAccount(rxObserver: RxObserver<UserInfoVo>, mView: LifecycleProvider<E>,             account: String, password: String) {
        sService.loginByAccount(HttpRequest.obtainHttpRequest(HttpEntry("account",account),
                HttpEntry("pwd", password)))//請求參數
                .compose(RxHelper.handleSingleResult())//封裝RXJava返回值的解析
                .bindToLifecycle(mView)//綁定生命週期
                .subscribe(rxObserver)
    }
}

2、retrofit類源碼分析

先看構造函數和成員變量

public final class Retrofit {
  private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();

  final okhttp3.Call.Factory callFactory;// 生產網絡請求器(Call)的工廠,默認使用OkHttp
  final HttpUrl baseUrl;// url地址
  final List<Converter.Factory> converterFactories;// 數據轉換器(converter)工廠
  final List<CallAdapter.Factory> callAdapterFactories;// 生產網絡請求適配器(CallAdapter)的工廠List
  final @Nullable Executor callbackExecutor;// 回調方法執行器
  final boolean validateEagerly; // 是否提前對業務接口中的註解進行驗證轉換的標誌位

  Retrofit(okhttp3.Call.Factory callFactory, HttpUrl baseUrl,
      List<Converter.Factory> converterFactories, List<CallAdapter.Factory> callAdapterFactories,
      @Nullable Executor callbackExecutor, boolean validateEagerly) {
    this.callFactory = callFactory;
    this.baseUrl = baseUrl;
    this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
    this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.
    this.callbackExecutor = callbackExecutor;
    this.validateEagerly = validateEagerly;
  }

  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()); // Retrofit支持Android Java8 默認Platform 三種平臺,此處確認當前是在哪個平臺環境運行
    }

    Builder(Retrofit retrofit) {
      platform = Platform.get();
      callFactory = retrofit.callFactory;
      baseUrl = retrofit.baseUrl;
        
      ****省略代碼
     }
}

retrofit是通過builder()方法來創建的,再看builder()方法:

 public Retrofit build() {
      //請求地址不可空
      if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
      }

      //默認爲OKHTTP
      okhttp3.Call.Factory callFactory = this.callFactory;
      if (callFactory == null) {
        callFactory = new OkHttpClient();
      }

      Executor callbackExecutor = this.callbackExecutor;
      if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
      }
        
      ***省略代碼
}

最後看create方法:關於動態代理的使用可以看看這篇文章https://blog.csdn.net/yaomingyang/article/details/80981004

  public <T> T create(final Class<T> service) {
    //校驗是否爲接口,且不能繼承其他接口
    Utils.validateServiceInterface(service);
     // 是否需要提前解析接口方法
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    //動態代理,返回一個 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 @Nullable 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);
          }
        });
  }

3、Platform類解析,用來支持java8版本之下的java平臺。

class Platform {
    ...
    // 無回調執行器,在哪裏創建的,就在哪裏回調
  Executor defaultCallbackExecutor() {
    return null;
  }
  // 平臺默認的回調適配器工廠列表爲new DefaultCallAdapterFactory(callbackExecutor)
  List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
      @Nullable Executor callbackExecutor) {
    return singletonList(new DefaultCallAdapterFactory(callbackExecutor));
  }
  // 默認回調適配器工廠數量爲1
    int defaultCallAdapterFactoriesSize() {
    return 1;
  }
  // 默認的轉換器工廠列表爲空列表
    List<? extends Converter.Factory> defaultConverterFactories() {
    return emptyList();
  }
  // 是否是默認方法
    boolean isDefaultMethod(Method method) {
    return false;
  }
  // 調用指定類默認的方法會拋異常,即不支持調用非默認方法
 @Nullable Object invokeDefaultMethod(Method method, Class<?> declaringClass, Object object,
      @Nullable Object... args) throws Throwable {
    throw new UnsupportedOperationException();
  }
    ...
    
}
  • isDefaultMethod()返回false,表示傳入的Method都告知不是默認方法(默認方法是一種公共的非抽象實例方法,即帶有主體的非靜態方法,在接口中聲明)
  • invokeDefaultMethod返回異常,表示調用非默認方法不支持

 

android

static class Android extends Platform {
    // 平臺默認的回調執行器 回調線程是UI線程
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }
    // 是否是默認方法
    @Override boolean isDefaultMethod(Method method) {
    // 如果安卓構建版本小於24(安卓7.0),則直接返回是非默認方法,否則正常返回method.isDefault()
      if (Build.VERSION.SDK_INT < 24) {
        return false;
      }
      return method.isDefault();
    }
    //回調執行器必須不爲空,回調適配器工廠列表版本小於Android7返回new DefaultCallAdapterFactory(callbackExecutor)單獨組成的不可變list,否則返回CompletableFutureCallAdapterFactory.INSTANCE和DefaultCallAdapterFactory(callbackExecutor)組成的不可變list
    @Override List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
        @Nullable Executor callbackExecutor) {
      if (callbackExecutor == null) throw new AssertionError();
      DefaultCallAdapterFactory executorFactory = new DefaultCallAdapterFactory(callbackExecutor);
      // CompletableFutureCallAdapterFactory是支持CompletableFutureCall,是java8特性
      return Build.VERSION.SDK_INT >= 24
        ? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
        : singletonList(executorFactory);
    }
    // 默認的回調適配器工程個數,和defaultCallAdapterFactories對應
    @Override int defaultCallAdapterFactoriesSize() {
      return Build.VERSION.SDK_INT >= 24 ? 2 : 1;
    }
    // 默認的轉換器工廠
    @Override List<? extends Converter.Factory> defaultConverterFactories() {
    // 如果平臺支持java8,則讓Converter支持java8操作符
      return Build.VERSION.SDK_INT >= 24
          ? singletonList(OptionalConverterFactory.INSTANCE)
          : Collections.<Converter.Factory>emptyList();
    }
    // 默認轉換器工廠個數
    @Override int defaultConverterFactoriesSize() {
      return Build.VERSION.SDK_INT >= 24 ? 1 : 0;
    }

    //安卓平臺的主線程執行器
    static class MainThreadExecutor implements Executor {
      private final Handler handler = new Handler(Looper.getMainLooper());

      @Override public void execute(Runnable r) {
        handler.post(r);
      }
    }
  }
  • Android有默認的MainThreadExecutor,就是Android主線程任務執行器,默認的CallAdapter.Factory任務回調適配器工廠。
  • 從這裏就可以看出Android平臺上,Retrofit執行任務默認是在主線程。

 

Java8

static class Java8 extends Platform {
  // 默認method.isDefault()
    @Override boolean isDefaultMethod(Method method) {
      return method.isDefault();
    }
    // 支持調用默認方法
    @Override Object invokeDefaultMethod(Method method, Class<?> declaringClass, Object object,
        @Nullable Object... args) throws Throwable {
      // Because the service interface might not be public, we need to use a MethodHandle lookup
      // that ignores the visibility of the declaringClass.
       //Java反射機制的構造器
      Constructor<Lookup> constructor = Lookup.class.getDeclaredConstructor(Class.class, int.class);
      constructor.setAccessible(true);
      return constructor.newInstance(declaringClass, -1 /* trusted */)
          .unreflectSpecial(method, declaringClass)
          .bindTo(object)
          .invokeWithArguments(args);
    }
    // 默認適配器工廠列表,和Android差不多
    @Override List<? extends CallAdapter.Factory> defaultCallAdapterFactories(
        @Nullable Executor callbackExecutor) {
      List<CallAdapter.Factory> factories = new ArrayList<>(2);
      factories.add(CompletableFutureCallAdapterFactory.INSTANCE);
      factories.add(new DefaultCallAdapterFactory(callbackExecutor));
      return unmodifiableList(factories);
    }
    // 默認適配器工廠個數
     @Override int defaultCallAdapterFactoriesSize() {
      return 2;
    }
    // 默認轉換器工廠列表
    @Override List<? extends Converter.Factory> defaultConverterFactories() {
      return singletonList(OptionalConverterFactory.INSTANCE);
    }
    // 默認轉換器工廠個數
    @Override int defaultConverterFactoriesSize() {
      return 1;
    }
  }

 

Retrofit源碼分析之二

Retrofit源碼分析之三

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章