public interface MyApi { @FormUrlEncoded @POST Call<ResponseBody> getData(@Field("userId") String userId); } 複製代碼
Retrofit retrofit = new Retrofit.Builder() .baseUrl("這裏放基礎url") .build(); 複製代碼
MyApi api = retrofit.create(MyApi.class);
複製代碼
Call<ResponseBody> call = api.getData("1234"); //post請求 call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { } }); //get請求 call.request(); 複製代碼
至此,一個簡單的使用retrofit網絡請求完成。java
推薦閱讀 這是一份很詳細的 Retrofit 2.0 使用教程(含實例講解)android
知其然知其因此然,一塊兒看看原理是怎麼實現的。api
Retrofit retrofit = new Retrofit.Builder() .baseUrl("這裏放基礎url") .build(); 複製代碼
建立了一個Builder對象,Buidler是Retrofit的靜態內部類bash
Builder(Platform platform) { this.platform = platform; } public Builder() { this(Platform.get()); } 複製代碼
這步很簡單,初始化Builder對象,調用的無參構造,方法內部將 Platform.get()
做爲參數又調用了本身的有參構造。markdown
咱們點開 Platform.get()
看看內部都作了什麼 `網絡
//靜態常量 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
對象,很顯然咱們是Android平臺。併發
總結:這一步就是 經過Platform
獲得了一個Builder
對象。ide
/** * Set the API base URL. * * @see #baseUrl(HttpUrl) */ public Builder baseUrl(String baseUrl) { //判空 checkNotNull(baseUrl, "baseUrl == null"); //將字符串形式的地址 解析爲 HttpUrl HttpUrl httpUrl = HttpUrl.parse(baseUrl); //判空呀 if (httpUrl == null) { throw new IllegalArgumentException("Illegal URL: " + baseUrl); } return baseUrl(httpUrl); } //最終調用 public Builder baseUrl(HttpUrl baseUrl) { //判空 checkNotNull(baseUrl, "baseUrl == null"); //把地址 以「/」分割,放進集合,爲了校驗地址 List<String> pathSegments = baseUrl.pathSegments(); //校驗地址不能以 「/」結尾 if (!"".equals(pathSegments.get(pathSegments.size() - 1))) { throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl); } this.baseUrl = baseUrl; return this; } 複製代碼
這一步就是對設置的baseUrl
進行校驗,最終輸出一個HttpUrl
類型的正確地址。oop
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(); } // Make a defensive copy of the adapters and add the default Call adapter. List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories); callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor)); // Make a defensive copy of the converters. List<Converter.Factory> converterFactories = new ArrayList<>(1 + this.converterFactories.size()); // 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); return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories), unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly); } 複製代碼
這個方法,主要就是校對參數,baseUrl不可爲空,callFactory就是okhttp的工廠實例,用於網絡請求的,其餘參數爲空則建立,最終攜帶這些參數建立了一個Retrofit
實例。源碼分析
總結:以上就是 初始化階段 的源碼分析 ,比較簡單,經過鏈式設置一系列參數,最終返回一個retrofit實例。
接下來的部分,整個過程比較長,並且是關鍵部分,通過幾番嘗試,發現 流程圖+文字分析 這種形式更加清晰。
推薦閱讀這篇文章 Retrofit原理解析最簡潔的思路
參考流程圖
Retrofit在create方法中採用動態代理模式實現接口方法,這個過程構建了一個ServiceMethod對象,根據方法註解獲取請求方式,參數類型和參數註解拼接請求的連接,當一切都準備好以後會把數據添加到Retrofit的RequestBuilder中。而後當咱們主動發起網絡請求的時候會調用okhttp發起網絡請求,okhttp的配置包括請求方式,URL等在Retrofit的RequestBuilder的build()方法中實現,併發起真正的網絡請求。