Retrofit 2.0源碼分析

Retrofit2.0是用註解的方式來描述一個HTTP請求,將HTTP請求抽象成一個Java的接口,然後用了Java動態代理的方式,將這個藉口的註解“翻譯”成一個HTTP請求,然後執行HTTP請求。
舉例說明:
請求一個api: https://api.github.com/repos/{owner}/{repo}/contributors
查看github上某個repo的contributors.
首先你要這樣建一個接口:
public interface GitHub {
	
	@GET("/repos/{owner}/{repo}/contributors")
	Call<List<Contributor>> contributors(@Path("owner")String owner,@Path("repo")String repo);
}
然後創建一個Retrofit
public static final String BASIC_URL="https://api.github.com";

Retrofit mRetrofit =new Retrofit.Builder().baseUrl(BASIC_URL).addConverterFactory
(GsonConverterFactory.create()).build();
創建一個GitHub
GitHub gitHub =mRetrofit.create(GitHub.class);
Call<List<Contributor>> call =gitHub.contributors("owner","repo");
最後回調獲取數據
call.enqueue(new Callback<List<Contributor>>(){
	@Override
	public void onResponse(Response<List<Contributor>>respone){
		for(Contributor controbutor: respone.body){


		}
	}


	@Override
	public void onFailure(Throwable t){


	}
});

create方法重要就是返回了一個動態代理對象。(Java動態代理就是Java開發給了開發人員一種可能:當你要調用某個類的方法前,插入你想要執行的代碼

比如你要執行某個操作前,你必須要判斷這個用戶是否登錄,或者你在付款前,你需要判斷這個人的賬戶中存在這麼多錢。這麼簡單的一句話,我相信可以把一個不懂技術的人也講明白Java動態代理是什麼東西了。)

// Create an instance of our GitHub API interface.
GitHub github = retrofit.create(GitHub.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, 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 loadMethodHandler(method).invoke(args);
      }
    });

生成一個HTTP請求就是這句:Call<List<Contributor>> call = github.contributors("square", "retrofit");
github是一個動態代理對象,並不是一個真正的Githb接口的implements對象,當github對象調用contributors方法時

,Retrofit其實是執行了動態代理的InvocationHandler對象,最後會創建一個MethodHandler對象(Github接口翻譯成一個HTTP請求,也就是MethodHandler對象),

這個對象中包含了4部分內容

static MethodHandler<?> create(Retrofit retrofit, Method method) {
    CallAdapter<Object> callAdapter = (CallAdapter<Object>) createCallAdapter(method, retrofit);
    Type responseType = callAdapter.responseType();
    Converter<ResponseBody, Object> responseConverter =
        (Converter<ResponseBody, Object>) createResponseConverter(method, retrofit, responseType);
    RequestFactory requestFactory = RequestFactoryParser.parse(method, responseType, retrofit);


    return new MethodHandler<>(retrofit.client(), requestFactory, callAdapter, responseConverter);
}
1. OkHttpClient:Retrofit默認生成的,發送網絡請求的工具
2. RequestFactory: 類似於Volley中的Request,包含了HTTP請求的Url、Header信息,MediaType、Method以及RequestAction數組,通過RequestFactoryParser.parse(method, responseType, retrofit)生成,主要作用就是解析整個Http請求的所有數據,得到整個Http請求全部的信息,通過@Path和@Query註解拼接Url
3.  CallAdapter:HTTP請求返回數據的類型
private static CallAdapter<?> createCallAdapter(Method method, Retrofit retrofit) {
  Type returnType = method.getGenericReturnType();
  if (Utils.hasUnresolvableType(returnType)) {
    throw Utils.methodError(method,
      "Method return type must not include a type variable or wildcard: %s", returnType);
  }
  if (returnType == void.class) {
    throw Utils.methodError(method, "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 Utils.methodError(e, method, "Unable to create call adapter for %s", returnType);
  }
}
4. Converter:數據轉換器,HTTP返回的數據解析成Java對象
 private static Converter<ResponseBody, ?> createResponseConverter(Method method,
  Retrofit retrofit, Type responseType) {
  Annotation[] annotations = method.getAnnotations();
  try {
    return retrofit.responseBodyConverter(responseType, annotations);
  } catch (RuntimeException e) { // Wide exception range because factories are user code.
    throw Utils.methodError(e, method, "Unable to create converter for %s", responseType);
  }
}

創建這4個對象的目的就是爲了執行下面這句代碼
Object invoke(Object... args) {
  return callAdapter.adapt(new OkHttpCall<>(client, requestFactory, responseConverter, args));
}
這個也就是github.contributors("square", "retrofit")返回的Call對象
最後你調用Call對象的execute()或enqueue(Callback<T> callback)方法,就能發送一個Http請求了

Retrofit接口
1.這個接口就是retrofit請求數據返回的接口,只有兩個方法
void onResponse(Response<T> response);
void onFailure(Throwable t);
2.Converter<F, T>
這個接口主要的作用就是將HTTP返回的數據解析成Java對象,主要由Xml、Gson、protobuf等等,你可以在創建Retrofit對象時添加你需要使用的Converter實現(看上面創建Retrofit對象的代碼)
3.Call<T>
這個接口主要的作用就是發送一個HTTP請求,Retrofit默認的實現是OkHttpCall<T>,你可以根據實際情況實現你自己的Call類,這個設計和Volley的HttpStack接口設計的思想非常相似,子類可以實現基於HttpClient或HttpUrlConnetction的HTTP請求工具,這種設計非常的插件化,而且靈活
4.CallAdapter<T>

上面說到過,CallAdapter中屬性只有responseType一個,還有一個<R> T adapt(Call<R> call)方法,這個接口的實現類也只有一個,DefaultCallAdapter。這個方法的主要作用就是將Call對象轉換成另一個對象,可能是爲了支持RxJava才設計這個類的吧。

===========================================》

文章轉載:http://bxbxbai.github.io/2015/12/13/retrofit2/

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