Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 網絡開源庫之-retrofit的解析詳解

Android 網絡開源庫之-retrofit的解析詳解

編輯:關於Android編程

前言

當前的網絡開源庫有許多,如volley,okhttp,retrofit等,這三個庫當前是比較火的,其中,okhttp和retrofit由square團隊開發。關於這三個庫的區別,請移步stackoverflow或者知乎查看。開發過程中選擇什麼樣的開源庫需要更具我們APP來做出選擇。我們選出stackoverflow中的一段話來看下。
\
上面說,需要與web service通信的時候,我們使用retrofit。百度百科 web service介紹,那麼我們見天就來了解下retrofit。

什麼是retrofit

關於什麼是retrofit,官網文檔上們有一句話。A type-safe HTTP client for Android and Java。額,似乎什麼也看出去來,就知道是一個類型安全的http client庫。那麼什麼是類型安全呢?類型安全代碼指訪問被授權可以訪問的內存位置。例如,類型安全代碼不能從其他對象的私有字段讀取值。它只從定義完善的允許方式訪問類型才能讀取。類型安全的代碼具備定義良好的數據類型。更多內容百度百科-類型安全,關於這裡還引用上面知乎的一句話。
\
RESTful-百度百科
rest-百度百科
上面這麼多抽象的概念太抽象,我們不管他。我們只需要知道retrofit確實是個很好的開源庫就可以了。

入門打老虎

開源庫是不錯,但是,你文檔能不能寫的詳細點。入門就是個大老虎。怎麼說呢,文檔給出的代碼精辟,但是不能運行。那麼,我們來看看具體的,真正的入門步驟。

1.在gradle腳本中添加

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

\
retrofit是中有用的okhttp,添加gson庫是為了將返回數據轉化為實體類。<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxoMyBpZD0="2將http-api轉化為java接口">2.將http api轉化為java接口

以下稱這貨為http接口
比如我們想去這個網址上獲取json數據。https://api.github.com/users/Guolei1130
你們也可以將Guolei1130替換為你們自己的github。

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

這裡使用注解,@GET表示我們的請求方式是get請求,@GET(“STR”),標明這裡的請求地址為BASEURL+STR,{user},這裡會在後面被getFeed的user參數替換,最後就拼接成了最終的請求路徑。返回的數據室什麼呢。Call< gitmodel>,這裡返回的Call是用來讓我們執行請求的。需要注意的是:Call< T>表示返回體中的數據,我們看下上面那個網址的返回數據。
\,很明顯是個json對象。
但是如果是返回數據為json數組的話我們就需要注意,這裡具體怎麼用還要根據返回數據以及我們的model來確定,倘若model對應json中的對象,便用Call< List< gitmodel>>,倘若對應json數組,用Call< gitmodel>。多的不說了,自己體會體會。

3.model的編寫

只需要將json對象的鍵值,編寫model對應的成員變量,在生成get set方法就好。
如圖:
\

4.執行請求

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

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

這裡我們先構造Retrofit對象,由於我們將返回的json數據轉化成了model對象,所以在構造Retrofit對象的時候,通過addConverterFactory來添加轉化器來完成數據轉化。
然後利用http接口的方法生成Call對象,最後用Call對象來執行http請求(異步和同步,後面會說到)。別忘記添加權限。
\
好,到這裡入門老虎就被我們打死了。

注解爽歪歪

我們既然知道了retrofit是通過注解將HTTP轉化為java接口,那麼我們就需要了解下都有哪些注解,該怎麼用。
\

請求方式

GET, POST, PUT, DELETE, 和 HEAD,我們平常開發中經常用的也就get和post。關於HTTP請求方式,這裡就不再說了,網上有很多介紹HTTP協議的文章,都特別詳細。
我們知道get請求方式,參數是放在路徑當中的。看下圖的路徑。
\
是不是很長,不過沒關系,用retrofit一樣可以將這麼長的串拼接到路徑中,怎麼做呢?
這裡就用到了@Query(一個鍵值對)和@QueryMap(多對鍵值對)。

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

上面代碼拼接出來的 = “http://baidu.com/s?wd=wdvalue“.
上面只是一個參數的時候,很多時候我們有許多參數,這個時候就需要我們使用@QueryMap 了

Call manykey(@QueryMap Map options);

上面的即可將多對鍵值對拼接到路徑當中。

請求體

我們知道post和get的區別當中有一點就是參數的位置,get放在url路徑當中,post放在請求體當中。
注意:前方高能,請仔細閱讀。前方高能,請仔細閱讀。前方高能,請仔細閱讀。下面我們模擬一個登錄,請求參數為用戶名和密碼,返回參數為我們的用戶名。

1.轉化為接口

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

2.編寫User和Des,用 來轉化數據

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.發送請求

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 model = service.post(new User("guolei","123456"));
                model.enqueue(new Callback() {
                    @Override
                    public void onResponse(Response response, Retrofit retrofit) {
                        Log.e(TAG, "onResponse: "+response.body().getDes());
                    }

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

客戶端的代碼很簡單,在這裡就不做過多的解釋。重點在於客戶端和服務器之間的交互。媽蛋,坑死我了。官方文檔上有一句話是這樣說的。
\
意思就是請求體對象也會轉化為json,剛開始我們並不知道會轉化為json,我們還傻傻的在php代碼中$_POST[‘username’],試了幾次沒效果之後。果斷拿出工具來分析。

抓包神器Charles,關於如何使用我這裡不說,我這裡只說下如何設置android端代理。長按鏈接的網絡-》修改 網絡-》將代理設為手動,輸入IP和端口。如下圖:
\
接下來,我們利用抓包工具去看看服務器接受的數據。如下圖:

果然,是json數據,但是我擦,我們明顯感覺這種數據我們沒法通過$_POST來接收。怎麼辦呢,不著急,咱們可以通過如下代碼來接收。php完整代碼如下(ps:只是演示,沒幾行)

$des);
    echo json_encode($arr);

恩,就這麼少,關於如下安裝php開發環境就不說了,so easy不是麼。最後,我們來看下效果圖:
\

表單編碼和多part

什麼叫表單,我想大家都應該知道,表單中有很多元素,我們這裡也不例外。在html代碼中,我們經常通過form表單來提交。在上面的請求體中,我們明顯感覺那玩意十分貌似有點難用。不過沒關系,我們有表單。
還是和上個例子一樣。

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

看下輸出結果;
\

這個多part是什麼呢,就是將請求提分為多個部分,這個就沒啥好說了的。

請求頭

我們知道http是有請求頭的,有些時候我們是需要填寫或者配置一下請求頭的,比如說,文件上傳,或者cookie保持。這裡的請求頭支持動態配置和靜態配置。

1.靜態配置

通過@Headers注解。如:下面這段是官方文檔上的。

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

2.動態配置

也來一段官方文檔上面的吧。

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

這些都相對簡單的,沒啥好說的,事實上,在開發過程中需要我們配置請求頭的地方也不多。

執行方式

這裡支持異步和同步。上面的例子中我們都是用的異步。那麼我們看下如何執行同步請求,也很簡單。

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

混淆代碼

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

retrofit+rxjava

在拋物線大大的RxJava入門當中,我們知道了retrofit和rxjava可以結合使用,那麼我們現在便來看看如何使用。

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 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.執行

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

在這裡我們要做好線程調度,現在網絡上那些坑爹的代碼,少一行代碼,把我坑了好長時間。喵了個咪的。最後看下效果圖。
\

總結

到這裡,還差我們網絡請求的其他需求,比如說文件上傳下載,cookie保持,https協議支持等。在okhttp中,這些東西都可以,retrofit作為okhttp的兄弟,我想也不會太差,還得繼續學習啊。
不過,在查了一些資料之後,我們知道,網絡庫的選擇要根據需求,一個很大的項目中用一個網絡庫很顯然是不可能的。那麼,okhttp+retrofit+圖片緩存庫+rxjava會不會成為日後開發的主流呢。還是期待吧。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved