Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Retrofit2 由淺入深

Retrofit2 由淺入深

編輯:關於Android編程

概述

在學習 Retrofit2 的過程中受到了一些阻力,現 Retrofit2 學會使用了,特此寫此文驗證所學知識。同時也希望幫助和我一樣在學習Retrofit2遇到困難的猿們。

當我在剛開始學習 Retrofit2 的時候並不知道Retrofit2是什麼東西,後來逐漸了解 “它可能是一個方便我們網絡請求的庫 ,可以幫我們讓請求網絡變得更靈活、易於維護”。然後還可以和時下比較火熱的RxJava進行完美融合。

先看看如何使用,如何進行一個簡單的Get/Post請求

Retrofit2 入門

首先在build.gradle中添加如下代碼,添加Retrofit2庫

compile 'com.squareup.retrofit2:retrofit:2.1.0'

有的教程裡寫要手動添加okhttp的庫,其實是不需要的,因為retrofit2封裝了okhttp,不信自己編譯下看看:

添加完庫,我們開始正文。

我們在項目中進行網絡請求時,肯定不是一個地址吧,那麼這些請求地址存放在哪呢?是在哪個類裡請求就在哪個類裡存放,還是統一放在一個專門存地址的類中呢?
我在學習Android期間就是哪裡有請求就放哪裡,後來有人告訴我要集中存放。於是後來就建立一個AppURL.java所有地址都存放這裡。
然而Retrofit2這裡也可以這麼理解:專門有一個‘地方’來存儲鏈接地址(也可以創建多個‘地方’存儲)。這個‘地方’不是類而是接口,在這個接口中可以設定請求地址的一些信息。就像這樣:

public interface AppURL { 
    @GET("index") 
    Call getIndex();
    ...
    ...
//  可以存儲多個連接地址
}

說明:
接口名“AppURL ”可以隨意定義,根據自己喜好。
第一行:代表get請求,請求地址為“設定的BaseURL/index” (BaseURL設定在下面介紹如何設定)
第二行:getIndex是方法名;Call是默認返回類型,暫且不要管能干什麼。

下面我們看下如何使用這些地址進行網絡請求:
1. 創建Retrofit對象,並設定BaseURL

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://www.這裡是BaseURL.com/")
                .build();

需要注意的是BaseURL必須以‘/’結尾

獲取“AppURL”對象(創建請求服務)
AppURL url= retrofit.create(AppURL.class);
用AppURL對象得到具體請求對象(獲取請求服務方法 )
Call call = getIndex.getIndex();

後期也會在這一步中進行設置鏈接參數、請求頭等

開始(異步)請求
call.enqueue(new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                Log.e("tag", response.body().toString());//獲得數據
            }
            @Override
            public void onFailure(Call call, Throwable t) {
                Log.e("tag", t.getMessage());//請求失敗
            }
        });

好了,現在一個簡單的網絡請求就寫完了。不是很難吧(當時我可是覺得挺難 ^_^)

單單會這些是遠遠不夠的,那麼我們如何來滿足項目中各種各樣的需求呢?請繼續看

Retrofit2 進階

自動解析

其實在Retrofit2中,我們不用自己來解析數據,Retrofit2可以幫我們自動解析,怎麼做呢?請看:
0. 添加
在Retrofit2中是用Gson解析的,所以我們要在build.gradle中添加。

compile 'com.squareup.retrofit2:converter-gson:2.1.0'

有寫教程說還有添加gosn庫,經過測試是不需要的,converter-gson中已經封裝了gson庫。
需要注意的是converter-gson和retrofit版本號應為一致,在這裡我都用2.1.0
1. 創建Bean
創建一個JavaBean,用於解析服務器返回數據。就和我們平常自己解析創建的Bean一樣,推薦用As的插件JsonFormat,挺方便的。
我們創建一個Bean起名為MBean.java(隨便起的)
2. 為retrofit添加addConverterFactory
添加後的代碼如下:

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://www.這裡是BaseURL.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();
修改泛型
//在AppURL 接口中修改:
@GET("index")
    Call getIndex();
 Call call = url.getIndex();
//調用服務請求時的修改
        call.enqueue(new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                Log.e("tag", response.body().toString());//解析好的數據
            }

            @Override
            public void onFailure(Call call, Throwable t) {
                Log.e("tag", t.getMessage());
            }
        });

這樣輸出的就直接是用Gson解析好的MBean數據了。

retrofit不僅僅只支持gson,還支持其他許多json解析庫。 如:
Jackson、Moshi、Protobuf、Wire、Simple XML、Scalars (primitives, boxed, and String) 具體請看官網

固定地址/路徑替換

說到固定地址了,那麼固定地址長什麼樣呢?

http://www.BaseURL.com/index
http://www.BaseURL.com/user
http://www.BaseURL.com/login
http://www.BaseURL.com/register/qq
http://www.BaseURL.com/register/wechat

那麼應該如何請求呢?除了上面例子中的寫法還可以這樣寫:

    @請求類型("{name}")
    Call<返回類型> 方法名(@path("name") String name);
如:

  @GET("{name}")
    Call get(@Path("name") String urlName);

//如果想訪問登錄的鏈接,在使用時就直接url.get("login");就可以。這樣請求的地址就是http://www.BaseURL.com/login 是不是很方便
//注意@Path和{}中的參數名要一致

@Path的應該作用暫且理解為 為上面的GET請求傳值

帶參地址

帶參地址長這樣子:

www.BaseURL.com/login?page=1
www.BaseURL.com/movieTop?start=1&count=5
www.BaseURL.com/login?username=testuser&password=123456

上個用的是@Path,這回用的是@Query其實和@Path一樣
直接看例子:

@GET("movieTop")
    Call get(@Query("start") int start, @Query("count") int count);
//假設想查詢電影排行榜的第1-5名,則使用時候是這樣:
Call call = url.get(1, 5);
//請求的地址是這樣:www.BaseURL.com/movieTop?start=1&count=5

Post帶Body請求

使用@Body來聲明即可,如下:

 @POST("/aaa")
 Call send( @Body UserInfo body);
//使用
Call call=url.send();

這裡的UserInfo就是要發送的實體,Retrofit2 會自動轉成Gson  

學到這裡,一般的網絡請求都可以了進行,可以應付一陣子了。
還有一些要求較高的請求,請看下節。

Retrofit2 大成

如果看到這裡,相信對Retrofit2的基本請求會用了,那麼這節就說一說其他的網絡請求。

表單(FormUrlEncoded)

我們可以使用@FormUrlEncoded注解來發送表單數據。使用 @Field注解和參數來指定每個表單項的Key,value為參數的值。

@FormUrlEncoded
@POST("user/login")
Call updateUser(@Field("username") String name, @Field("password") String pass);

單文件上傳(Multipart)

 @Multipart
    @POST("register")
    Call registerUser(
      @Part MultipartBody.Part headPhoto, 
      @Part("username") RequestBody userName, 
      @Part("password") RequestBody passWord
  );
//使用
MediaType textType = MediaType.parse("text/plain");
RequestBody name = RequestBody.create(textType, "二傻子");
RequestBody pass = RequestBody.create(textType, "123456");

RequestBody photoRequestBody = RequestBody.create(MediaType.parse("image/png"), 文件對象);
MultipartBody.Part photo = MultipartBody.Part.createFormData("上傳的key", "文件名.png", photoRequestBody);

Call call = url.registerUser(photo,name, pass);

@Part 後面支持三種類型,{@link RequestBody}、{@link okhttp3.MultipartBody.Part} 、任意類型;

動手測試:username的RequestBody 換成String是否可以

多文件上傳

@Multipart
@POST("register")
Call registerUser(@PartMap Map params,  @Part("password") RequestBody password);
//使用
RequestBody photo = RequestBody.create(MediaType.parse("image/png"), 文件對象2);
RequestBody photo = RequestBody.create(MediaType.parse("image/png"), 文件對象2);
Map photos = new HashMap<>();
photos.put("對應的key1"; filename=\"文件名1.png", photo1);
photos.put("對應的key2"; filename=\"文件名2.png", photo2);
photos.put("username",  RequestBody.create(null, "二傻子"));

Call call = userBiz.registerUser(photos, RequestBody.create(null, "123456"));

也可以都塞Map裡上傳,也可以只在Map中上傳文件,隨你喽~
文章結尾有參考鏈接。不一樣的上傳方式。

請求頭

固定請求頭
     @GET("地址")
     @Headers("Accept-Encoding: application/json")
     Call<返回類型> 方法名();
    // 請求結果:
    // GET 地址 HTTP/1.1
    // Accept-Encoding: application/json
動態請求頭
     @GET("地址")
     Call<返回類型> 方法名(@Header("Location") String location);
    //使用
    url.方法名("參數");
    // 請求結果:
    // GET 地址 HTTP/1.1
    // Location: 參數
固定+動態
     @GET("地址")
     @Headers("Accept-Encoding: application/json")
     Call<返回類型> 方法名(@Header("Location") String location);
    //使用
    url.方法名("參數");
    // 請求結果:
    // GET 地址 HTTP/1.1
    // Accept-Encoding: application/json
    // Location: 參數

其他

注意XXXMap的使用, 比如@PathMap,@FieldMap等,具體怎麼使用,可以自己研究,研究不出來的可以參考結尾處的文章。

下載文件得說說,在Retrofit2中下載文件是默認存儲到緩存中,也就是說不能進行大的文件下載,如果要下載大文件要用 @streaming 。但話說回來了,下載文件我們可以不用Retrofit2啊,直接用okhttp不就得啦

我們是可以添加 okhttpclient 到retrofit中去,這樣可以來統一的log管理,給每個請求添加統一的header等,那麼我們沒有添加為什麼沒有報錯呢? 因為在build()方法中會判斷是否為空,如果我們沒有添加okhttpclient 則就是空了,那麼retrofit會自動給我們添加了一個new OkHttpClient();

execute是同步執行 需要在子線程中執行、enqueue是異步執行。 看下我這幾個圖,整理一下思路吧以上表格中的除HTTP以外都對應了HTTP標准中的請求方法,而HTTP注解則可以代替以上方法中的任意一個注解,有3個屬性:method、path、hasBody, 
public interface BlogService {
    /**
     * method 表示請的方法,不區分大小寫
     * path表示路徑
     * hasBody表示是否有請求體
     */
    @HTTP(method = "get", path = "blog/{id}", hasBody = false)
    Call getFirstBlog(@Path("id") int id);
}

注1:{占位符}和PATH盡量只用在URL的path部分,url中的參數使用Query和QueryMap 代替,保證接口定義的簡潔
注2:Query、Field和Part這三者都支持數組和實現了Iterable接口的類型,如List,Set等,方便向後台傳遞數組。

    Call foo(@Query("ids[]") List ids);
    //結果:ids[]=0&ids[]=1&ids[]=2

Retrofit2 獨斷萬古

首先說下如何和當前火熱的RxJava進行配合使用。

引入RxJava支持 (版本號要一致)
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
寫接口
@GET(" ^_^ ")
    Observable get();
通過RxJavaCallAdapterFactory為Retrofit添加RxJava支持
Retrofit retrofit = new Retrofit.Builder()
      .baseUrl("http://www.BaseURL.com/")
      .addConverterFactory(GsonConverterFactory.create())//自動通過Gson轉josn,上面有提到
      .addCallAdapterFactory(RxJavaCallAdapterFactory.create())//添加RxJava支持
      .build();
使用
url.get()
        .subscribeOn(Schedulers.io())
        .subscribe(new Subscriber() {
            @Override
            public void onCompleted() {
            }
            @Override
            public void onError(Throwable e) {
            }
            @Override
            public void onNext(MBean mBean) {
            }
        });

根據需要添加RxAndroid,這個版本號沒有要求。

剩下的內容講的主要是進行自定義 Converter自定義CallAdapter。還有就是源碼的解析
這裡可以參考結尾處的鏈接,不獻丑了。

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