1. 程式人生 > >一個App帶你學會Retrofit2.0,麻麻再也不用擔心我的網路請求了!

一個App帶你學會Retrofit2.0,麻麻再也不用擔心我的網路請求了!

Retrofit、Retrofit、Retrofit,越來越多的人在玩這個網路請求框架,這個由squareup公司開源的網路請求框架確實挺好用,今天我們就來看一下這個東東怎麼玩!

Retrofit作為一個簡化的HTTP請求庫其實已經有很長一段時間了,只不過在早期的版本里有些地方用的不是特別爽,Retrofit從2.0開始修改了許多之前的痛點,現在不僅更好用而且功能也更加的強大。我們可以在Retrofit中利用介面、方法和註解引數等來宣告定義一個請求該如何被建立。同時它還有一個非常鮮明的特點就是支援REST風格的請求,同時它還很好的解決了執行緒非同步訪問問題,支援RxJava等。好了,廢話不多說,我們先來看看今天要實現的效果圖。


我們就來做這樣一個簡單的列表,看看如何使用Retrofit來實現。OK,這裡主要通過如下四步來使用Retrofit。

1.導包

2.定義API介面

3.初始化Retrofit

4.發起網路請求

1.導包

要使用Retrofit,首先肯定是導包,我這裡匯入兩個包,如下:

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

一個包是Retrofit的包,還有一個是Json轉換的工具包(具體作用看第三小節)。

2.定義API介面

接下來我們來定義相關的網路請求介面,在Retrofit2.0中,APIService的定義也將是一個非常簡單的事情,比如我們這個案例,我定義的APIService如下:

public interface ApiService {

    //獲取TabLayout上的資料
    @GET("api/lore/classify")
    Call<ClassfyBean> getClassfyData();
    
    //獲取首頁列表的資料
    @GET("api/lore/list")
    Call<CateItemBean> getListData(@Query("id") int id);

    //獲取詳情資料
    @GET("api/lore/show")
    Call<DetailBean> getDetailData(@Query("id") int id);
}

@GET表示該請求為一個get請求,常用的還有@POST表示該請求為一個POST請求。@GET後面的引數表示請求的路徑但是不包括域名,第一個方法由於是獲取TabLayout上的資料,這個介面不需要引數,第二第三個方法在請求資料時都需要傳遞引數,所以該方法帶有引數,@Query("id")表示該引數名為id。以第二個方法為例,帶引數的請求實際上等同這樣:api/lore/list?id=id,這裡需要注意的是,這種方式適用於get請求,POST請求還需要新增上@FormUrlEncoded註解,表示以表單的方式來提交引數。舉個栗子:
@FormUrlEncoded
    @POST("api/lore/list")
    Call<CateItemBean> getListData(@Field("id") int id);

Call請求接收一個泛型引數,該引數表示該請求的返回物件,Retrofit在收到返回值之後會根據我們傳遞的物件轉換工廠方法將返回值轉為該物件。

3.初始化Retrofit

定義好了APIService之後,接下來我們就可以初始化Retrofit了,Retrofit的初始化很簡單,如下:

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://www.tngou.net/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();

baseUrl其實就是我們請求地址的域名,這個域名配合上文的APIService中的引數才是一個完整的請求路徑。addConverterFactory表示一個新增一個轉換工廠,因為我這裡請求的資料是為JSON資料,所以新增GsonConverterFactory.create(),表示將接收到的Json資料轉換為一個DAO,官方提供的轉換工廠除了我們用的這個之外,還有如下幾個:
Gson: com.squareup.retrofit:converter-gson
Jackson: com.squareup.retrofit:converter-jackson
Moshi: com.squareup.retrofit:converter-moshi
Protobuf: com.squareup.retrofit:converter-protobuf
Wire: com.squareup.retrofit:converter-wire
Simple XML: com.squareup.retrofit:converter-simplexml
如果需要使用則把相應的包新增進來即可。

OK,這是一個最最基本的配置,Retrofit的網路請求使用了OKHttp,但是我們這裡怎麼沒有配置呢?如果你不配置,系統會預設建立一個OKHttp物件,如果你配置了那也沒問題,配置方式如下:

        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(5, TimeUnit.SECONDS)
                .readTimeout(10,TimeUnit.SECONDS)
                .build();
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://www.tngou.net/")
                .addConverterFactory(GsonConverterFactory.create())
                .client(client)
                .build();

4.發起網路請求

做完上面幾步之後,接下來我們就可以發起一個網路請求了,程式碼如下:

        ApiService apiService = retrofit.create(ApiService.class);
        Call<ClassfyBean> call = apiService.getClassfyData();
        call.enqueue(new Callback<ClassfyBean>() {
            @Override
            public void onResponse(Call<ClassfyBean> call, Response<ClassfyBean> response) {
                ClassfyBean body = response.body();
                List<Fragment> fragments = new ArrayList<Fragment>();
                for (int i = 0; i < body.getTngou().size(); i++) {
                    fragments.add(BaseFragment.getInstance(body.getTngou().get(i).getId()));
                }
                VpAdapter adapter = new VpAdapter(getSupportFragmentManager(), fragments, body);
                viewPager.setAdapter(adapter);
                tabLayout.setupWithViewPager(viewPager);
            }

            @Override
            public void onFailure(Call<ClassfyBean> call, Throwable t) {
                Log.d("google_lenve", "onFailure: "+t.getMessage());
            }
        });

在這裡,我們先通過retrofit.create方法獲取 一個APIService例項,然後呼叫該例項中對應的獲取資料的方法,獲取一個call,拿到call之後我們有兩個選擇(類似於OKHttp中的call),一個是呼叫call中的execute()方法獲取一個Response物件,程式碼如下:
Response<ClassfyBean> execute = call.execute();

但是這個方法會阻塞執行緒,在Android中如果呼叫這個方法需要我們將這一行程式碼放在子執行緒中執行,這無疑會增大我們的程式碼量。所以一個推薦的方法是呼叫call中的enqueue方法,這是一個非同步請求,類似於OKHttp中的enqueue,不同的是這裡的兩個回撥方法onResponse和onFailure都是在主執行緒中執行,意味著我們可以直接在這兩個回撥方法中更新UI,爽吧!

5.其他

以上幾個知識點已經可以實現我們的需求了,但是既然說到了Retrofit,那我們就再來聊聊它的其他一些功能點。

在Retrofit中還有一個註解叫做@Path,這個表示URL地址的一個佔位符,使用方式如下:

@GET("api/{id}/delete")
    Call<DetailBean> getData(@Path("id")String id);

還有一個註解@Header,表示新增請求頭資訊。。還有很多其他註解,由於用的比較少,我這裡就不再介紹了。

OK,這篇介紹就到這裡,後面我們再來說說Retrofit配合RxJava使用的問題。

以上。。。