Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Retrofi2源碼解析(二)

Retrofi2源碼解析(二)

編輯:關於Android編程

上一篇講解了retrofit2的簡單用法,這一邊主要解析一下reftofit2的原理,就從Retrofit的create(final Class service)方法看起,這個方法返回一個call對象,訪問網路是通過這個對象去訪問的。

我們先來看看create()這個方法裡干了些什麼:

 public  T create(final Class 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, 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 serviceMethod = loadServiceMethod(method);
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }
當看到proxy是不是有點眼熟呢,沒錯就是動態代理,主要使用newProxyInstance()方法來返回一個類的代理實例,它的參數需要傳遞一個類的加載器,類本身,以及InvocationHandler的子類對象,這裡它使用的是匿名內部類。主要動作都是在InvocationHandler中進行的,它裡面只有一個invoke()方法,每當我們調用代理類裡面的方法時,invoke()方法都會被執行,我們可以從參數中獲得很多信息,method的方法名,從args中獲取到方法的參數等。

 

invoke()方法裡主要做的就是:

首先,將method轉換為serviceMethod;

然後,通過serviceMethod,arg獲取到okHttpCall對象;

最後,通過serviceMethod.callAdapter.adapt()對okHttpCall進行封裝返回call對象。

下面一步步來分析。

一、將method轉換為serviceMethod

 

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

這裡很容易理解,就是通過ServiceMethod的構造器構造一個serviceMethod對象,並把它緩存起來。下面來看看這個構造器的build(0方法裡都干了些啥:

 

 

public Builder(Retrofit retrofit, Method method) {
      this.retrofit = retrofit;
      this.method = method;
      this.methodAnnotations = method.getAnnotations();
      this.parameterTypes = method.getGenericParameterTypes();
      this.parameterAnnotationsArray = method.getParameterAnnotations();
    }

 

 

public ServiceMethod build() {
      callAdapter = createCallAdapter();
      responseType = callAdapter.responseType();
      if (responseType == Response.class || responseType == okhttp3.Response.class) {
        throw methodError("'"
            + Utils.getRawType(responseType).getName()
            + "' is not a valid response body type. Did you mean ResponseBody?");
      }
      responseConverter = createResponseConverter();

      ...
      return new ServiceMethod<>(this);
    }
首先在builder的構造方法裡初始化一些參數,然後再build()方法裡通過new ServiceMethod(),並將這個對象返回來獲得servicMethod對象,下面來仔細看看build()方法:

 

1、createCallAdapter()獲得callAdapter,源碼如下:

 

private CallAdapter createCallAdapter() {
      Type returnType = method.getGenericReturnType();
      if (Utils.hasUnresolvableType(returnType)) {
        throw methodError(
            "Method return type must not include a type variable or wildcard: %s", returnType);
      }
      if (returnType == void.class) {
        throw methodError("Service methods cannot return void.");
      }
      Annotation[] annotations = method.getAnnotations();
      try {
        return retrofit.callAdapter(returnType, annotations);
      } catch (RuntimeException e) { // Wide exception range because factories are user code.
        throw methodError(e, "Unable to create call adapter for %s", returnType);
      }
    }
這個方法裡最主要就是獲取到method的類型和注解,然後調用了retrofit的callAdapter()方法,

 

 

public CallAdapter callAdapter(Type returnType, Annotation[] annotations) {
    return nextCallAdapter(null, returnType, annotations);
  }
而retrofit的callAdapter()方法調用的是自己的nextCallAdapter()方法:

 

 

public CallAdapter nextCallAdapter(CallAdapter.Factory skipPast, Type returnType,
      Annotation[] annotations) {
    checkNotNull(returnType, "returnType == null");
    checkNotNull(annotations, "annotations == null");

    int start = adapterFactories.indexOf(skipPast) + 1;
    for (int i = start, count = adapterFactories.size(); i < count; i++) {
      CallAdapter adapter = adapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }

這個方法裡,遍歷了adapterFactories,從中獲取callAdapter對象,adapterFactories這個集合中有哪些calAdapter對象呢,

 

 

public static final classBuilder {
    ...
    publicBuilderaddCallAdapterFactory(CallAdapter.Factory factory) {
      adapterFactories.add(checkNotNull(factory, "factory == null"));
      return this;
    }
    ...
    public Retrofitbuild() {
      List adapterFactories = newArrayList<>(this.adapterFactories);
      adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
    ...
    }  
  }

CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
    if(callbackExecutor != null) {
      return new ExecutorCallAdapterFactory(callbackExecutor);
    }
    return DefaultCallAdapterFactory.INSTANCE;
  }
上面的代碼中我們可以看到,不管我們有沒有往adapterFactories中添加元素,adapterFactories集合中都至少會有一個ExcutorCallAdapterFactory對象,也就是說上面通過createCallAdapter()方法得到的callAdapter就是ExcutorCallAdapterFactory,這個在後面很關鍵。

 

2、createResponseConverter()得到responseConverter轉換器對象,它的作用是尋找合適的數據類型轉換器,

這個的過程和構造callAdapter對象基本一致,這裡不再贅述。

二、通過serviceMethod,arg獲取到okHttpCall對象

 

OkHttpCall(ServiceMethod serviceMethod, Object[] args) {
    this.serviceMethod = serviceMethod;
    this.args = args;
  }
這一步比較簡單,就是傳遞參數

 

 

三、通過serviceMethod.callAdapter.adapt()對okHttpCall進行封裝返回call對象

我們知道serviceMethod.callAdapter就是ExcutorCallAdapterFactory,那我們只要看ExcutorCallAdapterFactory的adapt()方法就可以了:
 T adapt(Call call);
就這麼一句,這是嘛呀,但是經過第一步的分析,我們已知道serviceMethod.callAdapter就是ExecutorCallAdapterFactory,那麼我們可以看看在ExecutorCallAdapterFactory類中有沒有發現CallAdapter的另類應用呢,一看,果不其然在重寫父類的get()方法中我們找到了答案:
@Override
  public CallAdapter> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
    if (getRawType(returnType) != Call.class) {
      return null;
    }
    final Type responseType = Utils.getCallResponseType(returnType);
    return new CallAdapter>() {
      @Override public Type responseType() {return responseType;
      }

      @Override public  Call adapt(Call call) {return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
    };
  }
 

當看到return new CallAdapter中的adapt(Call call)我們就完全知其所以然了,至於ExecutorCallbackCall怎麼應用的我們在發起網絡請求的時候講解。

ok,當我們得到接口的代理實例之後,通過代理接口調用裡面的方法,就會觸發InvocationHandler對象中的invoke方法,從而完成上面的三個步驟並且返回一個Call對象,通過Call對象就可以去完成我們的請求了,Retrofit為我們提供兩種請求方式,一種是同步,一種是異步。我們這裡就以異步方式來講解:

當我們通過retrofit的create()方法獲得call對象,再調用call.enque()去訪問網絡時,方法中有回掉函數,回掉函數裡重寫兩個方法,一個成功,一個失敗,來看下怎麼回事,這個call對象其實就是ExcutorCallAdapterFactory,來看裡面具體實現:
public static final classExecutorCallbackCall implementsCall {
    finalExecutorcallbackExecutor;
    finalCall delegate;

    ExecutorCallbackCall(Executor callbackExecutor, Call delegate) {
      this.callbackExecutor = callbackExecutor;
      this.delegate = delegate;
    }

    @Overridepublicvoidenqueue(final Callback callback) {
      if(callback == null)thrownewNullPointerException("callback == null");

      delegate.enqueue(new Callback() {
        @Override public void onResponse(Call call, final Response response) {
          callbackExecutor.execute(new Runnable() {
            @Override public void run() {
              if (delegate.isCanceled()) {
                callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
              } else {
                callback.onResponse(ExecutorCallbackCall.this, response);
              }
            }
          });
        }

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

在ExecutorCallbackCall類中,封裝了兩個對象一個是callbackExecutor,它主要是把現在運行的線程切換到主線程中去,一個是delegate對象,這個對象就是真真正正的執行網絡操作的對象,那麼它的真身到底是什麼呢?還記得我們在獲取代理接口第三步執行的serviceMethod.callAdapter.adapt(okHttpCall)的分析吧,經過輾轉幾步終於把okHttpCall傳遞到了new ExecutorCallbackCall<>(callbackExecutor, call);中,然後看看ExecutorCallbackCall的構造方法:
 
ExecutorCallbackCall(Executor callbackExecutor, Call delegate) {
      this.callbackExecutor = callbackExecutor;
      this.delegate = delegate;
    }

可以知道delegate即使okHttpCall對象,來看okHttCall怎麼異步訪問網絡的:
@Override 
public void enqueue(final Callback callback) {
    if (callback == null) throw new NullPointerException("callback == null");

    okhttp3.Call call;
    Throwable failure;

    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      call = rawCall;
      failure = creationFailure;
      if (call == null && failure == null) {
        try {
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          failure = creationFailure = t;
        }
      }
    }

    if (failure != null) {
      callback.onFailure(this, failure);
      return;
    }

    if (canceled) {
      call.cancel();
    }

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

      @Override 
      public void onFailure(okhttp3.Call call, IOException e) {
        try {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

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

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

上面的代碼中可以看到,裡面封裝了一個okhttp3.Call對象,直接利用okhttp進行異步網絡訪問,okhttp怎麼訪問網絡的這裡不再講解,感興趣的可以自行翻看源碼。 好了到這裡,retrofit訪問網絡的原理基本解析完畢,希望能對大家有幫助,有什麼不對之處還請多多指正。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved