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源碼查看和總結

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,431評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,637評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,555評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,900評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,629評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,976評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,976評論 3 448
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,139評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,686評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,411評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,641評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,129評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,820評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,233評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,567評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,362評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,604評論 2 380

推薦閱讀更多精彩內容