Android 網(wǎng)絡(luò)開(kāi)源庫(kù)-Retrofit(一)簡(jiǎn)單介紹

?前言

當(dāng)前的網(wǎng)絡(luò)開(kāi)源庫(kù)有許多茂装,如volley,okhttp善延,retrofit等少态,這三個(gè)庫(kù)當(dāng)前是比較火的,其中易遣,okhttp和retrofit由square團(tuán)隊(duì)開(kāi)發(fā)彼妻。關(guān)于這三個(gè)庫(kù)的區(qū)別,請(qǐng)移步?stackoverflow或者?知乎查看。開(kāi)發(fā)過(guò)程中選擇什么樣的開(kāi)源庫(kù)需要更具我們APP來(lái)做出選擇侨歉。我們選出stackoverflow中的一段話來(lái)看下屋摇。


上面說(shuō),需要與web service通信的時(shí)候幽邓,我們使用retrofit摊册。?百度百科 web service介紹,那么我們見(jiàn)天就來(lái)了解下retrofit颊艳。

?什么是retrofit

關(guān)于什么是retrofit,官網(wǎng)文檔上們有一句話忘分。A type-safe HTTP client for Android and Java棋枕。額,似乎什么也看出去來(lái)妒峦,就知道是一個(gè)類型安全的http client庫(kù)重斑。那么什么是類型安全呢?類型安全代碼指訪問(wèn)被授權(quán)可以訪問(wèn)的內(nèi)存位置肯骇。例如窥浪,類型安全代碼不能從其他對(duì)象的私有字段讀取值。它只從定義完善的允許方式訪問(wèn)類型才能讀取笛丙。類型安全的代碼具備定義良好的數(shù)據(jù)類型漾脂。更多內(nèi)容?百度百科-類型安全,關(guān)于這里還引用上面知乎的一句話胚鸯。


RESTful-百度百科
?rest-百度百科
上面這么多抽象的概念太抽象骨稿,我們不管他。我們只需要知道retrofit確實(shí)是個(gè)很好的開(kāi)源庫(kù)就可以了姜钳。

入門打老虎

開(kāi)源庫(kù)是不錯(cuò)坦冠,但是,你文檔能不能寫(xiě)的詳細(xì)點(diǎn)哥桥。入門就是個(gè)大老虎辙浑。怎么說(shuō)呢,文檔給出的代碼精辟拟糕,但是不能運(yùn)行判呕。那么,我們來(lái)看看具體的已卸,真正的入門步驟佛玄。

1.在gradle腳本中添加

compile 'com.squareup.retrofit:retrofit:2.0.0-beta2'
compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'

retrofit是中有用的okhttp,添加gson庫(kù)是為了將返回?cái)?shù)據(jù)轉(zhuǎn)化為實(shí)體類累澡。

2.將http api轉(zhuǎn)化為java接口

以下稱這貨為http接口
比如我們想去這個(gè)網(wǎng)址上獲取json數(shù)據(jù)梦抢。https://api.github.com/users/Guolei1130
你們也可以將Guolei1130替換為你們自己的github。

public interface gitapi {
    @GET("/users/{user}")
    Call<gitmodel> getFeed(@Path("user") String user);
}

這里使用注解愧哟,@GET表示我們的請(qǐng)求方式是get請(qǐng)求奥吩,@GET("STR")哼蛆,標(biāo)明這里的請(qǐng)求地址為BASEURL+STR,{user}霞赫,這里會(huì)在后面被getFeed的user參數(shù)替換腮介,最后就拼接成了最終的請(qǐng)求路徑。返回的數(shù)據(jù)室什么呢端衰。Call< gitmodel>叠洗,這里返回的Call是用來(lái)讓我們執(zhí)行請(qǐng)求的。需要注意的是:Call< T>表示返回體中的數(shù)據(jù)旅东,我們看下上面那個(gè)網(wǎng)址的返回?cái)?shù)據(jù)灭抑。


,很明顯是個(gè)json對(duì)象抵代。
但是如果是返回?cái)?shù)據(jù)為json數(shù)組的話我們就需要注意腾节,這里具體怎么用還要根據(jù)返回?cái)?shù)據(jù)以及我們的model來(lái)確定,倘若model對(duì)應(yīng)json中的對(duì)象荤牍,便用Call< List< gitmodel>>,倘若對(duì)應(yīng)json數(shù)組案腺,用Call< gitmodel>。多的不說(shuō)了康吵,自己體會(huì)體會(huì)劈榨。

3.model的編寫(xiě)

只需要將json對(duì)象的鍵值待秃,編寫(xiě)model對(duì)應(yīng)的成員變量齐媒,在生成get set方法就好油狂。
如圖:


4.執(zhí)行請(qǐng)求

Retrofit retrofit= new Retrofit.Builder()
          .baseUrl("https://api.github.com")
          .addConverterFactory(GsonConverterFactory.create())
          .build();
gitapi service = retrofit.create(gitapi.class);
Call<gitmodel> model = service.getFeed("Guolei1130");
model.enqueue(new Callback<gitmodel>() {
      @Override
      public void onResponse(Response<gitmodel> response, Retrofit retrofit) {
             Log.e(TAG, "onResponse: "+response.body().getLogin() );
           }

       @Override
       public void onFailure(Throwable t) {
              Log.e(TAG, "onFailure: " + t.getMessage());
           }
});

這里我們先構(gòu)造Retrofit對(duì)象神郊,由于我們將返回的json數(shù)據(jù)轉(zhuǎn)化成了model對(duì)象逛万,所以在構(gòu)造Retrofit對(duì)象的時(shí)候畦戒,通過(guò)addConverterFactory來(lái)添加轉(zhuǎn)化器來(lái)完成數(shù)據(jù)轉(zhuǎn)化季俩。
然后利用http接口的方法生成Call對(duì)象昼蛀,最后用Call對(duì)象來(lái)執(zhí)行http請(qǐng)求(異步和同步棕兼,后面會(huì)說(shuō)到)陡舅。別忘記添加權(quán)限。



好伴挚,到這里入門老虎就被我們打死了靶衍。

?注解爽歪歪

我們既然知道了retrofit是通過(guò)注解將HTTP轉(zhuǎn)化為java接口,那么我們就需要了解下都有哪些注解茎芋,該怎么用颅眶。


請(qǐng)求方式

GET, POST, PUT, DELETE, 和 HEAD,我們平常開(kāi)發(fā)中經(jīng)常用的也就get和post田弥。關(guān)于HTTP請(qǐng)求方式涛酗,這里就不再說(shuō)了,網(wǎng)上有很多介紹HTTP協(xié)議的文章,都特別詳細(xì)商叹。
我們知道get請(qǐng)求方式燕刻,參數(shù)是放在路徑當(dāng)中的∑鼠希看下圖的路徑卵洗。



是不是很長(zhǎng)弥咪,不過(guò)沒(méi)關(guān)系过蹂,用retrofit一樣可以將這么長(zhǎng)的串拼接到路徑中,怎么做呢聚至?
這里就用到了@Query(一個(gè)鍵值對(duì))和@QueryMap(多對(duì)鍵值對(duì))榴啸。

// 假設(shè) baseurl = "http://baidu.com"
    @GET("/s")
    Call<gitmodel> onekey(@Query("wd") String wdvalue);

上面代碼拼接出來(lái)的 = "http://baidu.com/s?wd=wdvalue".
上面只是一個(gè)參數(shù)的時(shí)候,很多時(shí)候我們有許多參數(shù)晚岭,這個(gè)時(shí)候就需要我們使用@QueryMap 了

Call<gitmodel> manykey(@QueryMap Map<String, String> options);

上面的即可將多對(duì)鍵值對(duì)拼接到路徑當(dāng)中。

請(qǐng)求體

我們知道post和get的區(qū)別當(dāng)中有一點(diǎn)就是參數(shù)的位置勋功,get放在url路徑當(dāng)中坦报,post放在請(qǐng)求體當(dāng)中。
注意:前方高能狂鞋,請(qǐng)仔細(xì)閱讀片择。前方高能,請(qǐng)仔細(xì)閱讀骚揍。前方高能字管,請(qǐng)仔細(xì)閱讀。下面我們模擬一個(gè)登錄信不,請(qǐng)求參數(shù)為用戶名和密碼嘲叔,返回參數(shù)為我們的用戶名。

1.轉(zhuǎn)化為接口

@POST("/index.php")
Call<Des> post(@Body User user);

2.編寫(xiě)User和Des抽活,用 來(lái)轉(zhuǎn)化數(shù)據(jù)

public class Des {
    public String des;

    public String getDes() {
        return des;
    }

    public void setDes(String des) {
        this.des = des;
    }
}
public class User {
    public String username;
    public String password;

    public User(String username,String password){
        this.username = username;
        this.password = password;
    }
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

3.發(fā)送請(qǐng)求

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

                gitapi service = retrofit.create(gitapi.class);
                Call<Des> model = service.post(new User("guolei","123456"));
                model.enqueue(new Callback<Des>() {
                    @Override
                    public void onResponse(Response<Des> response, Retrofit retrofit) {
                        Log.e(TAG, "onResponse: "+response.body().getDes());
                    }

                    @Override
                    public void onFailure(Throwable t) {
                        Log.e(TAG, "onFailure: "+t.getMessage() );
                    }
                });

客戶端的代碼很簡(jiǎn)單硫戈,在這里就不做過(guò)多的解釋。重點(diǎn)在于客戶端和服務(wù)器之間的交互下硕。媽蛋丁逝,坑死我了。官方文檔上有一句話是這樣說(shuō)的梭姓。



意思就是請(qǐng)求體對(duì)象也會(huì)轉(zhuǎn)化為json霜幼,剛開(kāi)始我們并不知道會(huì)轉(zhuǎn)化為json,我們還傻傻的在php代碼中$_POST['username']誉尖,試了幾次沒(méi)效果之后罪既。果斷拿出工具來(lái)分析。

?抓包神器Charles,關(guān)于如何使用我這里不說(shuō)萝衩,我這里只說(shuō)下如何設(shè)置android端代理回挽。長(zhǎng)按鏈接的網(wǎng)絡(luò)-》修改 網(wǎng)絡(luò)-》將代理設(shè)為手動(dòng),輸入IP和端口猩谊。如下圖:

千劈。
接下來(lái),我們利用抓包工具去看看服務(wù)器接受的數(shù)據(jù)牌捷。如下圖:
墙牌,
果然,是json數(shù)據(jù)暗甥,但是我擦喜滨,我們明顯感覺(jué)這種數(shù)據(jù)我們沒(méi)法通過(guò)$_POST來(lái)接收。怎么辦呢撤防,不著急虽风,咱們可以通過(guò)如下代碼來(lái)接收。php完整代碼如下(ps:只是演示寄月,沒(méi)幾行)

<?php 
    
     
    $var=file_get_contents("php://input");
     

    $obj= json_decode($var,true);
    $des = $obj['username'];
    $arr =  array("des"=>$des);
    echo json_encode($arr);

    

恩辜膝,就這么少,關(guān)于如下安裝php開(kāi)發(fā)環(huán)境就不說(shuō)了漾肮,so easy不是么厂抖。最后,我們來(lái)看下效果圖:


表單編碼和多part

什么叫表單克懊,我想大家都應(yīng)該知道忱辅,表單中有很多元素,我們這里也不例外谭溉。在html代碼中墙懂,我們經(jīng)常通過(guò)form表單來(lái)提交。在上面的請(qǐng)求體中扮念,我們明顯感覺(jué)那玩意十分貌似有點(diǎn)難用垒在。不過(guò)沒(méi)關(guān)系,我們有表單扔亥。
還是和上個(gè)例子一樣场躯。

@FormUrlEncoded
@POST("/index.php")
Call<Des> form(@Field("username") String username,@Field("password") String password);
Call<Des> model = service.form("guolei","123456");

看下輸出結(jié)果;


這個(gè)多part是什么呢,就是將請(qǐng)求提分為多個(gè)部分旅挤,這個(gè)就沒(méi)啥好說(shuō)了的踢关。

請(qǐng)求頭

我們知道http是有請(qǐng)求頭的,有些時(shí)候我們是需要填寫(xiě)或者配置一下請(qǐng)求頭的粘茄,比如說(shuō)签舞,文件上傳秕脓,或者cookie保持。這里的請(qǐng)求頭支持動(dòng)態(tài)配置和靜態(tài)配置儒搭。

1.靜態(tài)配置

通過(guò)@Headers注解吠架。如:下面這段是官方文檔上的。

@Headers({
    "Accept: application/vnd.github.v3.full+json",
    "User-Agent: Retrofit-Sample-App"
})

2.動(dòng)態(tài)配置

也來(lái)一段官方文檔上面的吧搂鲫。

@GET("/user")
Call<User> getUser(@Header("Authorization") String authorization)

這些都相對(duì)簡(jiǎn)單的傍药,沒(méi)啥好說(shuō)的,事實(shí)上魂仍,在開(kāi)發(fā)過(guò)程中需要我們配置請(qǐng)求頭的地方也不多拐辽。

執(zhí)行方式

這里支持異步和同步。上面的例子中我們都是用的異步擦酌。那么我們看下如何執(zhí)行同步請(qǐng)求俱诸,也很簡(jiǎn)單。

//同步請(qǐng)求
//model.execute().body().getLogin();

混淆代碼

-dontwarn retrofit.**
-keep class retrofit.** { *; }
-keepattributes Signature
-keepattributes Exceptions

?retrofit+rxjava

在拋物線大大的RxJava入門當(dāng)中赊舶,我們知道了retrofit和rxjava可以結(jié)合使用睁搭,那么我們現(xiàn)在便來(lái)看看如何使用。

1.添加

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.0.1'
    compile 'com.squareup.retrofit:retrofit:2.0.0-beta2'
    compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2'
    compile 'io.reactivex:rxjava:1.0.16'
    compile 'io.reactivex:rxandroid:1.0.1'
    compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2'
}

2.http api接口

@FormUrlEncoded
@POST("/index.php")
public Observable<Des> rxpost(@Field("username") String username,@Field("password") String password);

3.在retrofit中添加RxJavaCallAdapterFactory

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

4.執(zhí)行

gitapi service = retrofit.create(gitapi.class);
                Observable<Des>  observable =  service.rxpost("quanshijie", "123456");
                observable.observeOn(AndroidSchedulers.mainThread())
                        .subscribeOn(Schedulers.newThread())
                        .subscribe(new Action1<Des>() {
                            @Override
                            public void call(Des des) {
                                Log.e(TAG, "call: " + des.getDes().toString());
                                mText.setText(des.getDes().toString());
                            }
                        }, new Action1<Throwable>() {
                            @Override
                            public void call(Throwable throwable) {
                                Log.e(TAG, "call: " + throwable.getLocalizedMessage());
                            }
                        });

在這里我們要做好線程調(diào)度笼平,現(xiàn)在網(wǎng)絡(luò)上那些坑爹的代碼介袜,少一行代碼,把我坑了好長(zhǎng)時(shí)間出吹。喵了個(gè)咪的。最后看下效果圖辙喂。


?總結(jié)

到這里捶牢,還差我們網(wǎng)絡(luò)請(qǐng)求的其他需求,比如說(shuō)文件上傳下載巍耗,cookie保持秋麸,https協(xié)議支持等。在okhttp中炬太,這些東西都可以灸蟆,retrofit作為okhttp的兄弟,我想也不會(huì)太差亲族,還得繼續(xù)學(xué)習(xí)啊炒考。
不過(guò),在查了一些資料之后霎迫,我們知道斋枢,網(wǎng)絡(luò)庫(kù)的選擇要根據(jù)需求,一個(gè)很大的項(xiàng)目中用一個(gè)網(wǎng)絡(luò)庫(kù)很顯然是不可能的知给。那么瓤帚,okhttp+retrofit+圖片緩存庫(kù)+rxjava會(huì)不會(huì)成為日后開(kāi)發(fā)的主流呢描姚。還是期待吧。
好累啊戈次,到現(xiàn)在飯都沒(méi)吃轩勘。retrofit的坑還是有的。我估計(jì)剩下的三點(diǎn)地方坑更大怯邪,不扯了绊寻,收工。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末擎颖,一起剝皮案震驚了整個(gè)濱河市榛斯,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌搂捧,老刑警劉巖驮俗,帶你破解...
    沈念sama閱讀 216,919評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異允跑,居然都是意外死亡王凑,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門聋丝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)索烹,“玉大人,你說(shuō)我怎么就攤上這事弱睦“傩眨” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,316評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵况木,是天一觀的道長(zhǎng)垒拢。 經(jīng)常有香客問(wèn)我,道長(zhǎng)火惊,這世上最難降的妖魔是什么求类? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,294評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮屹耐,結(jié)果婚禮上尸疆,老公的妹妹穿的比我還像新娘。我一直安慰自己惶岭,他們只是感情好寿弱,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,318評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著按灶,像睡著了一般脖捻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上兆衅,一...
    開(kāi)封第一講書(shū)人閱讀 51,245評(píng)論 1 299
  • 那天地沮,我揣著相機(jī)與錄音嗜浮,去河邊找鬼。 笑死摩疑,一個(gè)胖子當(dāng)著我的面吹牛危融,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播雷袋,決...
    沈念sama閱讀 40,120評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼吉殃,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了楷怒?” 一聲冷哼從身側(cè)響起蛋勺,我...
    開(kāi)封第一講書(shū)人閱讀 38,964評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鸠删,沒(méi)想到半個(gè)月后抱完,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,376評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡刃泡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,592評(píng)論 2 333
  • 正文 我和宋清朗相戀三年巧娱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片烘贴。...
    茶點(diǎn)故事閱讀 39,764評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡禁添,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出桨踪,到底是詐尸還是另有隱情老翘,我是刑警寧澤,帶...
    沈念sama閱讀 35,460評(píng)論 5 344
  • 正文 年R本政府宣布锻离,位于F島的核電站铺峭,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏纳账。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,070評(píng)論 3 327
  • 文/蒙蒙 一捺疼、第九天 我趴在偏房一處隱蔽的房頂上張望疏虫。 院中可真熱鬧,春花似錦啤呼、人聲如沸卧秘。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,697評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)翅敌。三九已至,卻和暖如春惕蹄,著一層夾襖步出監(jiān)牢的瞬間蚯涮,已是汗流浹背治专。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,846評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留遭顶,地道東北人张峰。 一個(gè)月前我還...
    沈念sama閱讀 47,819評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像棒旗,于是被迫代替她去往敵國(guó)和親喘批。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,665評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,089評(píng)論 25 707
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理铣揉,服務(wù)發(fā)現(xiàn)饶深,斷路器,智...
    卡卡羅2017閱讀 134,654評(píng)論 18 139
  • 前言 在Android開(kāi)發(fā)中逛拱,網(wǎng)絡(luò)請(qǐng)求十分常用 而在Android網(wǎng)絡(luò)請(qǐng)求庫(kù)中敌厘,Retrofit是當(dāng)下最熱的一個(gè)網(wǎng)...
    Carson帶你學(xué)安卓閱讀 70,720評(píng)論 48 393
  • 文/婷婷愛(ài)甜不愛(ài)酸 01 她和他在一起7年额湘,今天是她們戀愛(ài)七周年的紀(jì)念日。人們總說(shuō)會(huì)有七年之癢旁舰,她想锋华,也許她和他會(huì)...
    蘇木啊閱讀 2,071評(píng)論 44 43
  • sources :Python 3 programming tutorial: While Loop_Youtube
    HuafengLu閱讀 183評(píng)論 0 0