Retrofit2源碼解析(一)

本文基於Retrofit2的2.4.0版本

implementation 'com.squareup.retrofit2:retrofit:2.4.0'

Retrofit2底層基於OkHttp3,是對利用OkHttp3請求網絡的一種封裝,可以使我們避免寫很多重複的調用網絡請求的代碼,同時靈活性很高,可以定製自定義的OkHttpClient、自定義的數據解析轉換器(比如Gson、Jackson等)、自定義的請求轉換器(比如結合RxJava)。

Retrofit2的另一個特點就是使用運行時註解,我們在使用時可以根據需要來利用註解將我們的業務調用接口轉換成Http請求的接口。

下面先來看看我們使用Retrofit2發起網絡請求的步驟

(1)創建我們的具體業務接口,這裏比如我們調用淘寶的IP地址庫

public interface MyService {
    @GET("getIpInfo.php=11.11.11.11")
    Call<IpBean> getData();
}

(2)創建Retrofit

retrofit = new Retrofit.Builder()
    .baseUrl("https://ip.taobao.com/service/")
    .addConverterFactory(GsonConverterFactory.create())
    .build();

可見Retrofit2採用的是Builder模式來構建的

(3)利用Retrofit創建我們的接口對象,生成Call對象,並調用請求網絡方法

MyService myService = retrofit.create(MyService.class);
Call<IpBean> call = myService.getData();
call.enqueue(new Callback<IpBean>() {
    @Override
    public void onResponse(Call<IpBean> call, Response<IpBean> response) {
        
    }

    @Override
    public void onFailure(Call<IpBean> call, Throwable t) {
        
    }
});

Retrofit的創建

首先我們看看創建Retrofit時都做了哪些工作

public Retrofit build() {
    //這裏可以看出我們必需設置baseUrl
    if (baseUrl == null) {
        throw new IllegalStateException("Base URL required.");
    }
    
    //如果我們沒有設置自定義的OkHttpClient,就用默認的OkHttpClient
    okhttp3.Call.Factory callFactory = this.callFactory;
    if (callFactory == null) {
        callFactory = new OkHttpClient();
    }
    
    //這個callbackExecutor用於回調到UI線程
    Executor callbackExecutor = this.callbackExecutor;
    if (callbackExecutor == null) {
        callbackExecutor = platform.defaultCallbackExecutor();
    }

    //將我們設置的Call適配器添加到列表中,比如RxJava的適配器
    List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
    //添加默認的Call適配器
    callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

    // Make a defensive copy of the converters.
    List<Converter.Factory> converterFactories =
            new ArrayList<>(1 + this.converterFactories.size());

    //添加數據轉換器,用於將網絡請求返回的結果轉換成我們需要的類型
    converterFactories.add(new BuiltInConverters());
    converterFactories.addAll(this.converterFactories);
    
    //構建Retrofit
    return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
            unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}

通過上面Retrofit2的Builder的build方法,我們可以看出在Retrofit2中主要有這麼幾個部分:

(1)用於執行具體網絡請求的callFactory,也就是OkHttpClient。所以說Retrofit2是基於OkHttp3的封裝。

(2)callbackExecutor回調執行器,這個是用於網絡請求返回後回調到主線程的。我們知道,在利用OkHttp3進行網絡請求時,我們需要手動回調到主線程,以便更新UI。那我們來看看這個默認的defaultCallbackExecutor是不是這樣。

//Retrofit.class
public Builder() {
    this(Platform.get());
}

Builder(Platform platform) {
    this.platform = platform;
}

可以看到在Builder中調用的是Platform的get方法,返回對應的平臺,然後在build方法裏通過platform的defaultCallbackExecutor得到我們的回調器。下面我們看看這個Platform類

class Platform {
    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();
    }
    
    ...
    
    static class Android extends Platform {
        @Override
        public Executor defaultCallbackExecutor() {
            return new MainThreadExecutor();
        }

        @Override
        CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
            if (callbackExecutor == null) throw new AssertionError();
            return new ExecutorCallAdapterFactory(callbackExecutor);
        }

        static class MainThreadExecutor implements Executor {
            private final Handler handler = new Handler(Looper.getMainLooper());

            @Override
            public void execute(Runnable r) {
                handler.post(r);
            }
        }
    }
}

從上面的源碼中我們可以看到Platform中會根據當前運行的平臺返回不同的子類,這裏當然就是Android這個內部類了。所以當我們調用platform的defaultCallbackExecutor時,實際上調用的是Android這個類的defaultCallbackExecutor方法,而這個方法返回的是MainThreadExecutor,它的作用就是利用handler將執行結果回調到主線程中。

(3)callAdapterFactories適配器列表,這裏面存放的是所有的Call適配器CallAdapter。這個CallAdapter是幹嘛的呢?我們知道Retrofit2底層是用Okhttp3來請求網絡的,那勢必是通過OkHttp3的Call來執行請求,但是我們在實際使用Retrofit2時,可能需要結合請他的三方庫,常見的比如RxJava,那我們接口中所需要返回的可能就是Observable而不是Call了。

@GET("getIpInfo.php?ip=11.11.11.11")
Observable<IpBean> getObservableData();

所以Retrofit2就需要一個Call適配器CallAdapter,來將Call轉換爲我們需要的Observable,這就是CallAdapter的作用。

(4)converterFactories返回結果轉換器列表,這裏面存放的是將網絡返回結果,也就是OkHttp3返回的Response,解析轉換成我們需要的實際類型,比如IpBean實體類。如GsonConverterFactory就是一個常用的轉換器,相當於Retrofit2把我們直接使用Okhttp3來請求網絡數據時需要將返回結果進行Gson解析的動作也替我們做了。

總結

(1)這裏我們簡單分析了Retrofit的創建過程,可以發現Retrofit中核心部分包括OkHttpClient、Call適配器、Response轉換器以及用於將請求回調到UI線程的回調執行器等。

(2)Retrofit的創建採用的是Builder模式,定製化程度很高,我們可以設置自己的OkHttpClient,也可以實現自定義的Call適配器和Response轉換器,以及請求的回調執行器。

(3)可見Retrofit雖然做了很大程度的封裝,但是靈活性擴展性依然很高,我們幾乎可以擴展更改網絡請求的大部分過程。

今天我們先淺嘗則止,後面我們再來具體分析下Retrofit2的網絡調用過程,看看Retrofit2是怎麼利用適配器模式來爲我們提供強大的靈活性的,敬請期待。



歡迎關注我的微信公衆號,和我一起每天進步一點點!
AntDream
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章