Retrofit原始碼解讀(一)--Retrofit簡單流程

若蘭__明月發表於2018-01-08

Retrofit原始碼解讀(一)--Retrofit簡單流程

標籤(空格分隔):Retrofit原始碼 學習筆記


Retrofit

不是網路請求框架,而是對網路請求框架的封裝,是整個框架的門面類,整個入口,可以通過這個方法進行我們的請求的配置,配置的方式就是通過裡面的一個內部類Builder,使用構建者模式建立,裡面有個重要的變數就是ServiceMethod

ServiceMethod

對應我們寫好的介面類中的方法,通過動態代理的模式,通過這個可以將我們定義好的方法(包含方法裡面的引數,註解)轉換成一個一個的http請求。同時ServiceMethod可以幫我們解析方法中的註解,生成我們需要的Request物件。在ServiceMethod這個類中生成了三個重要的工廠類CallAdapter工廠Converter工廠

  • CallAdapter工廠 預設把網路請求封裝成okhttpcall,這個作用就是將okhttpcall轉換成適合不同平臺使用的解析(比如java8,ios,android平臺)
  • Converter工廠 是用於生產資料轉換,預設情況下是把okhttp返回的response物件轉換成我們的java物件進行使用。而在Retrofit裡面預設是使用Gson來解析資料
  • CallFactory工廠 用於建立Call請求類,http請求會抽象封裝成call類,同時表示請求已經準備好了,隨時可以執行

這個時候通過這幾個工廠類的建立和配合,可以建立出OkHttpCall請求,可以進行同步或者非同步請求,可以看出,Retrofit只是對okhttpcall的一層封裝,底層還是通過okhttp進行的網路請求。

當通過okhttpcall進行請求,對之前ServiceMethod生成的一些地址,引數,請求之後(同步或者非同步都行),返回結果之後,就會通過之前建立好的CallAdapter工廠,把okhttpcall轉換成不同平臺使用的。

然後通過Converter進行資料轉換,最終得到一個response物件,然後最後通過callbackExecutor進行執行緒切換(子執行緒請求資料,主執行緒更新UI),當然了這個只是針對非同步請求,同步請求是不需要這個的。

簡單的使用

請求流程

首先確定的一點就是,Retrofit是一個網路請求框架的封裝工具類,而不是一個網路請求框架,他底層使用的是okhttp這個網路請求框架,只是在okhttp的基礎上進行了更深層次的封裝,更加簡單易用。所以流程就是

App->Retrofit: 傳送請求

Retrofit-->App: 資料(解析好)

Retrofit->OkHttp: 我要請求資料

OkHttp-->Retrofit: 請求好資料返回

OkHttp->Server: 後臺,給我資料

Server-->OkHttp: 吶,資料給你
複製程式碼
  • App應用程式通過Retrofit請求網路,實際上是使用Retrofit介面層封裝請求引數和HTTP方式,之後交由OkHttp完成後續的網路請求工作
  • 在服務端返回資料之後,OkHttp將原始的結果交給Retrofit,Retrofit根據使用者的需求對資料進行解析,然後進行相關邏輯操作

程式碼演示

例子一
  • Retrofit turns your HTTP API into a Java interface.
public interface GitHubService {
    // @GET  表示get請求方法
    // users/{user}/repos  這個就是和baseurl進行拼接 是個完整的請求地址
    //{user}  這個大括號,表示裡面的引數是動態的可以更換的  具體的值就是對應@Path("user") String user  這個傳遞進入的user
  @GET("users/{user}/repos")
  Call<List<Repo>> listRepos(@Path("user") String user);
}
複製程式碼
  • The Retrofit class generates an implementation of the GitHubService interface.
Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .build();

GitHubService service = retrofit.create(GitHubService.class);

複製程式碼
  • Each Call from the created GitHubService can make a synchronous or asynchronous HTTP request to the remote webserver.
Call<List<Repo>> repos = service.listRepos("octocat");
複製程式碼
repos.enqueue(new Callback(){
    
    @Override
    public void onFailure(Call call,IOException e){
            //請求出錯進行的邏輯
    }
    
    @Override
    public void onResponse(Call call ,Response response) throws IOException{
        //在這裡進行的是成功資料只會的相關請求
    }
})
複製程式碼

上述的程式碼演示就是官網的簡單示例 點選這裡

例子二

1、新增網路許可權

 <uses-permission android:name="android.permission.INTERNET"/>
複製程式碼

2、建立一個接受的返回型別

class HttpResult<T> {

    private int count;
    private int err;
    private int total;
    private int page;
    private int refresh;

    //用來模仿Data
    private T items;

}

class TestBean{
    private String format;

    private long published_at;

    private String content;
    private String state;
}


 public class User {

        /**
         * avatar_updated_at : 1418571809
         * uid : 13846208
         * last_visited_at : 1390853782
         * created_at : 1390853782
         * state : active
         * last_device : android_2.6.4
         * role : n
         * login : ---切隨緣
         * id : 13846208
         * icon : 20141215074328.jpg
         */

        private int avatar_updated_at;
        private int uid;
        private int last_visited_at;
        private int created_at;
        private String state;
        private String last_device;
        private String role;
        private String login;
        private int id;
        private String icon;
}
複製程式碼

3、建立服務介面


public interface TestInterface {
    //每個方法引數都需要進行註解標誌 要不然就會報錯  這個在後面的分析詳細邏輯的時候會講
    @GET("article/list/latest?page=1")
    Call<HttpResult<List<TestBean>>> getQiuShiJsonString();

}

複製程式碼

4、建立Retrofit例項

 public static Retrofit getRetrofit() {

        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.connectTimeout(10, TimeUnit.SECONDS);


        return new Retrofit.Builder()
                .client(builder.build())
                //設定請求網路地址的url(基地址  這個地址一定要"/"結尾  要不會出現問題)
                // 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("http://m2.qiushibaike.com/")  
                .addConverterFactory(GsonConverterFactory.create()) //設定資料解析器  預設使用的Gson
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) //設定支援RxJava轉換器
                .build();

    }
複製程式碼

5、建立網路請求的介面例項

   TestInterface service = getRetrofit().create(TestInterface.class);
複製程式碼

6、通過介面例項建立call方法

 Call<HttpResult<List<TestBean>>> qiuShiJson = service.getQiuShiJsonString();
複製程式碼

7、通過call執行非同步(或者同步方法)

 qiuShiJson.enqueue(new Callback<HttpResult<List<TestBean>>>() {
            @Override
            public void onResponse(Call<HttpResult<List<TestBean>>> call, Response<HttpResult<List<TestBean>>> response) {
                Log.d("TestRetrofit", "請求回來的資料");
                if (response.isSuccessful()){
                    HttpResult<List<TestBean>> body = response.body();
                    Log.d("TestRetrofit", "body.getSubjects().size():" + body.getSubjects().size());
                }
            }

            @Override
            public void onFailure(Call<HttpResult<List<TestBean>>> call, Throwable t) {
                Log.d("TestRetrofit", "請求資料失敗,失敗的原因" + t.getMessage());
            }
        });

複製程式碼

專案地址

開源專案Retrofit原始碼檢視和總結
開源專案Retrofit原始碼檢視和總結
開源專案Retrofit原始碼檢視和總結

相關文章