Retrofit入門

Retrofit使用

Retrofit官方文檔java

一、添加依賴

在Maven中使用:git

<dependency>
  <groupId>com.squareup.retrofit2</groupId>
  <artifactId>retrofit</artifactId>
  <version>2.9.0</version>
</dependency>
複製代碼

在Gradle中使用:github

// retrofit2依賴
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
// Gson依賴
implementation "com.squareup.retrofit2:converter-gson:2.5.0"
implementation "com.google.code.gson:gson:2.8.6"
// 日誌攔截器
implementation 'com.squareup.okhttp3:logging-interceptor:3.3.1'  
複製代碼

注意:版本號可能會不同,具體到官網進行查找設計模式

二、建立請求接口

將全部的接口方法都寫在這裏面markdown

由於Retrofit是經過Interface來管理HTTP API,並且這個接口不能繼承其餘接口網絡

public interface RemoteService {

    /** * 網絡請求一個註冊接口 * * @param model RegisterModel * @return RspModel<AccountRspModel> */
    @POST("account/register")
    Call<RspModel<AccountRspModel>> accountRegister(@Body RegisterModel model);
}
複製代碼

三、網絡請求的封裝

在項目中,爲了不代碼冗餘,咱們常常會將網絡請求進行一個總體的封裝,以單例模式架構

/** * 網絡請求的封裝 * * @author : iwen大大怪 * @create : 12-7 007 18:19 */
public class Network {
    // 單例模式
    private static Network instance;
    private OkHttpClient client;
    private Retrofit retrofit;

    static {
        instance = new Network();
    }

    private Network() {
    }
    /** * 步驟1:構建一個Retrofit */
    public static Retrofit getRetrofit() {
        if (instance.retrofit != null){
            return instance.retrofit;
        }
        // 步驟:2:獲得一個OkHttpClient
        OkHttpClient client = new OkHttpClient.Builder()
                // 跳過ssh檢查
                .sslSocketFactory(OkHttpSSH.createSSLSocketFactory(), new OkHttpSSH.TrustAllCerts())
                .connectTimeout(10, TimeUnit.SECONDS)// 設置超時時間
                .writeTimeout(10, TimeUnit.SECONDS)// 設置寫入超時時間
                .readTimeout(20, TimeUnit.SECONDS)// 設置讀取超時時間
                // 給全部的請求添加一個攔截器(看具體需求)
                //.addInterceptor()
                .build();
        
        // 步驟3:獲取Retrofit對象
        Retrofit.Builder builder = new Retrofit.Builder();
        instance.retrofit = builder
            	.baseUrl("根據須要填寫")
                .client(client) // 設置client
                .addConverterFactory(GsonConverterFactory.create()) // 設置數據解析器
                .build();
        return instance.retrofit;
    }

    /** * 步驟4:返回一個請求代理 * @return RemoteService */
    public static RemoteService mRemoteService(){
       // 傳入具體接口類,將其轉換成動態代理
       return Network.getRetrofit().create(RemoteService.class);
    }
}
複製代碼

四、使用

RemoteService service = Network.mRemoteService();
// 調用具體接口請求的方法
Call<RspModel<LogoutRspModel>> call = service.accountRegister(model);
// 發起異步請求
call.enqueue(new Callback<RspModel<LogoutRspModel>>() {
    @Override
    public void onResponse(Call<RspModel<LogoutRspModel>> call, Response<RspModel<LogoutRspModel>> response) {
    // 請求成功回調
    }

    @Override
    public void onFailure(Call<RspModel<LogoutRspModel>> call, Throwable t) {
    // 請求失敗回調
    }
});
複製代碼

Retrofit架構解析

一、Okhttp的缺陷

  1. **問題一:**用戶網絡請求接口配置繁瑣,尤爲是須要配置複雜的請求Body、請求頭、參數的時候。
  2. **問題二:**數據解析過程須要用戶手動拿到responsbody進行解析,不能複用。
  3. **問題三:**沒法適配自動進行線程切換。
  4. **問題四:**一旦存在嵌套網絡請求,就會陷入「回調陷阱」。

二、Retrofit是什麼?

準確來講,Retrofit是一個RESTful的HTTP網絡請求框架的封裝。框架

**緣由:**網絡請求的工做本質仍是由OKHTTP完成,而Retrofit只是負責網絡請求接口的封裝。ssh

三、Retrofit設計的任務

tempimg-1302248544.cos.ap-chengdu.myqcloud.com/Img/PingMu/…異步

請求前:

  1. 統一的配置網絡請求頭:使用建造者模式、門面模式來對一些參數進行統一的配置,而且將其保存。

  2. 一致適配請求request:create()方法裏面使用了動態代理模式,這樣子就能夠代理全部類對象。

請求後:

  1. 線程切換:

  2. 數據適配:

四、Retrofit封裝的點

  1. Build 模式建立網絡請求的基本配置。(解決了問題一)
  2. 用註解來排列組合合成網絡請求,以不變應萬變。(解決了問題一)
  3. 統一提供Gson解析,提供可複用,易拓展的數據解析方案。(解決了問題二)
  4. 自定義Executor(Handler)完成線程的切換。(解決了問題三)

Retrofit這個類就是保存一系列的參數給後面使用,使用的是Build模式

五、Retrofit設計模式

在構建Retrofit時,採用的是建造者模式、外觀模式

在適配一致請求request時:Create()方法裏面使用了動態代理模式

靜態代理模式:

  • 代理類和委託類有一樣的接口。
  • 代理類主要負責爲委託類預處理消息、過濾消息、把消息轉發給委託類,以及過後的消息處理等。
  • 一個代理類的對象與一個委託類的對象關聯,代理類的對象自己並不真正的實現服務,而是經過調用委託類的對象的相關方法,來提供服務。

動態代理模式:

代理類在程序運行前不存在、運行時由程序動態生成的代理方式稱爲動態代理。

傳進去咱們接口的類對象便可生成對應的實例並調用具體方法,是由於這裏面實際上retrofit利用動態代理模式生成了一個代理對象(而且實現了RemoteService),而後一旦調用了RemoteService的方法,就會觸發代理對象的invoke方法,從而在invoke總攔截並得到了RemoteService的全部方法以及對應的那些@GET @POST 等Retrofit的註解信息,而後利用OKhttp完成真正的請求操做。

juejin.cn/post/684490…

create(RemoteService.class);
複製代碼

這一行的時候,虛擬機內部生成了代理類的Class二進制流,而且加載到虛擬機中造成代理類的Class對象,再反射獲得代理類對象,而該代理類即實現了GitHubService,而且持有了InvocationHandler的引用。

咱們從Retrofitcreate方法一探究竟:

public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    // 經過Proxy.newProxyInstance生成了代理類
    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生成了代理類,並new了一個匿名內部InvocationHandler對象,重寫它的invoke方法,至關於經過咱們傳進來的接口,生成了一個接口的代理類,而且實現了接口是全部方法(由於InvocationHandler的參數裏傳進去了new Class<?>[] { service }),而後返回給外部。 外部一旦調用了接口方法,例如request.getData();,就會觸發InvocationHandlerinvoke,從而根據註解生成Retrofit的ServiceMethodOkHttpCall對象,這些都是發起網絡請求的必備信息,而後最終發起請求。

相關文章
相關標籤/搜索