Retrofit初探

前言

Retrofit現在真的是炒雞火,前不久用了之后,并且與rxjava配合得簡直天衣無縫,我便深深的愛上了這個框架。

概述

Retrofit是Square公司開發,針對Android網絡請求的框架。通過文檔http://square.github.io/retrofit/可以看到它的介紹

A type-safe HTTP client for Android and Java

簡單的說它就是一個HTTP請求工具,這里提到了類型安全,而Retrofit就是通過聲明泛型來實現類型安全的,也就是說通過聲明泛型能夠約束最終我們想要的對象是什么。

用法

Retrofit 可以利用接口,方法和注解參數(parameter annotations)來聲明式定義一個請求應該如何被創建。這里酷炫的注解參數也是我深深喜愛這個框架的原因之一。比如我們需要請求以下的API

https://api.github.com/repos/{owner}/{repo}/contributors

查看GitHub上"owner"的"repo"中的contributors,首先要創建一個以下的接口:

public interface GitHubService {
    @GET("/repos/{owner}/{repo}/contributors")
    Call<List<Contributor>> repoContributors(
        @Path("owner") String owner,
        @Path("repo") String repo);
}

然后通過Retrofit生成一個此接口的實現類:

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .build();

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

默認的,Retrofit只能接收OkHttp'sRequestBody并轉換成OkHttp'sResponseBody,不過在這里在創建Retrofit對象時,可以根據需要加入Converters,同時還需要在build.gradle中添加依賴。

  • Gson: com.squareup.retrofit2:converter-gson
  • Jackson: com.squareup.retrofit2:converter-jackson
  • Moshi: com.squareup.retrofit2:converter-moshi
  • Protobuf: com.squareup.retrofit2:converter-protobuf
  • Wire: com.squareup.retrofit2:converter-wire
  • Simple XML: com.squareup.retrofit2:converter-simplexml
  • Scalars (primitives, boxed, and String): com.squareup.retrofit2:converter-scalars

這里獲取的是json數據,那么修改代碼成:

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .addConverterFactory(GsonConverterFactory.create())
    .build();

接著獲取接口中Call的實例:

Call<List<Contributor>> call = service.repoContributors("square", "retrofit");

最后就可以通過執行call獲取到數據了:

call.enqueue(new Callback<List<Contributor>>() {
    @Override
    public void onResponse(Response<List<Contributor>> response) {
        for (Contributor contributor : response.body()) {
            System.out.println(contributor.login + ":" + contributor.contributions );
        }
    }
    @Override
    public void onFailure(Throwable t) {
    }
});

這里的Contributor就是我們創建的數據bean類,在此例子的api中,我們可以獲取到很多數據,但是我們只需要篩選自己需要的數據創建一個bean類傳入就可以了。

public class Contributor{
    String login;
    int contributions;
}

支持rxjava

當然,Retrofit還支持rxjava,這時我們需要在創建Retrofit實例的時候再加入一個adapter:

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl("https://api.github.com/")
    .addConverterFactory(GsonConverterFactory.create())
    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
    .build();

之前的接口也需要修改,這時候我們需要返回的不再是Call,而是Observable

public interface GitHubService {
    @GET("/repos/{owner}/{repo}/contributors")
    Observable<List<Contributor>> repoContributors(
        @Path("owner") String owner,
        @Path("repo") String repo);
}

獲取到Observable實例之后就是一連串的rxjava的代碼,比如子線程生產數據,主線程消費數據,更新UI等等。

service.repoContributors("square", "retrofit")
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Subscriber<List<Contributor>>() {
            @Override
            public void onStart() {
                showProgressBar();
            }

            @Override
            public void onCompleted() {
                dismissProgressBar();
            }

            @Override
            public void onError(Throwable e) {
                Log.i(">>>", "onError " + e.toString());
            }

            @Override
            public void onNext(List<Contributor> list) {
                for (Contributor contributor : list) {
                        System.out.println(contributor.login + ":" + contributor.contributions );
                }
            }
        });

注解詞

前面說到了Retrofit可以通過注解參數的方式來聲明定義一個請求,一下就來介紹其中重要的注解詞用法。

GET請求

  1. @Query

    Get方法請求參數都會以key=value的方式拼接在url后面。

     Retrofit retrofit = new Retrofit.Builder()
             .baseUrl("https://api.douban.com/v2/")
             .addConverterFactory(GsonConverterFactory.create())
             .build();
    
     Call<BookBean> call = retrofit.create(DemoService.class).queryDemo(1);
     String url = call.request().url().toString();
     Log.i(">>>", "onCreate :" + url);
    

打印結果:</br>
https://api.douban.com/list?page=1

  1. @QueryMap

    如果拼接在后面的參數過多,可以通過QueryMap方式將所有的參數集成在一個Map集合中傳遞。

     Retrofit retrofit = new Retrofit.Builder()
             .baseUrl("https://api.douban.com/v2/")
             .addConverterFactory(GsonConverterFactory.create())
             .build();
    
     Map<String, String> options = new HashMap<>();
     options.put("start", "0");
     options.put("count", "3");
    
     Call<BookBean> call = retrofit.create(DemoService.class).queryMapDemo(options);
     String url = call.request().url().toString();
     Log.i(">>>", "onCreate :" + url);
    

打印結果:</br>
https://api.douban.com/v2/book/search?count=3&start=0

  1. @Path

    在url中的參數需要請求方提供的時候,可以利用path。

     Retrofit retrofit = new Retrofit.Builder()
             .baseUrl("https://api.douban.com/v2/")
             .addConverterFactory(GsonConverterFactory.create())
             .build();
    
     Call<BookBean> call = retrofit.create(DemoService.class).pathDemo(1);
     String url = call.request().url().toString();
     Log.i(">>>", "onCreate :" + url);
    

打印結果:</br>
https://api.douban.com/image/1

POST請求

  1. @Field

    POST請求需要把參數放置在請求體中,而不是拼接在url后面。

     Retrofit retrofit = new Retrofit.Builder()
             .baseUrl("https://api.douban.com/v2/")
             .addConverterFactory(GsonConverterFactory.create())
             .build();
    
     Call<BookBean> call = retrofit.create(DemoService.class).fieldDemo("zhangsan", "businessman");
    
    • 這里的注解還需要一個@FormUrlEncoded,將會自動將請求參數的類型調整為application/x-www-form-urlencoded。
  2. @FieldMap

    如果有更多的請求參數的時候,通過一個一個的參數傳遞就顯得很麻煩而且容易出錯,那么這個時候就可以用FieldMap

     Retrofit retrofit = new Retrofit.Builder()
             .baseUrl("https://api.douban.com/v2/")
             .addConverterFactory(GsonConverterFactory.create())
             .build();
    
     Map<String, String> fields = new HashMap<>();
     fields.put("start", "0");
     fields.put("count", "3");
    
     Call<BookBean> call = retrofit.create(DemoService.class).fieldMapDemo(fields);
    

Demo GitHub:https://github.com/cgzysan/RetrofitDemo</br>
同時我也用Retrofit寫了一個Gnak.iohttps://github.com/cgzysan/Gank.io</br>
Retrofit未完待續!

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

推薦閱讀更多精彩內容