天天看點

一種類型安全的Java HTTP用戶端庫Retrofit一種類型安全的Java HTTP用戶端庫Retrofit

版權聲明:本文為部落客chszs的原創文章,未經部落客允許不得轉載。 https://blog.csdn.net/chszs/article/details/50920944

一種類型安全的Java HTTP用戶端庫Retrofit

作者:chszs,未經部落客允許不得轉載。經許可的轉載需注明作者和部落格首頁: http://blog.csdn.net/chszs

一、Retrofit介紹

Retrofit是一個開源的、類型安全的HTTP用戶端,它适用于Android和Java平台,官方首頁為:

http://square.github.io/retrofit/

Retrofit需要Java 7以上版本或Android 2.3以上版本的支援。

二、Retrofit依賴

Retrofit的Maven依賴:

<dependency>
<groupId>com.squareup.retrofit2</groupId>
<artifactId>retrofit</artifactId>
<version>2.0.0</version>
</dependency>
           

Gradle依賴:

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

三、Retrofit用法

1、Retrofit定義HTTP服務接口GitHubService

public interface GitHubService {
    @GET("users/{user}/repos")
    Call<List<Repo>> listRepos(@Path("user") String user);
}
           

2、Retrofit産生GitHubService接口的實作

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

從GitHubService接口的每一個Call都可以向遠端伺服器發起同步或異步的請求。

Call<List<Repo>> repos = service.listRepos("octocat");
           

3、使用注釋描述HTTP請求

  • URL參數替代和查詢參數的支援
  • 對象轉換成請求的Body
  • 請求的Body可分拆為多個部分,支援檔案上傳

四、API聲明

接口方法和參數上的注釋說明了應該如何處理請求。

1、請求方法

每一個方法都必須有一個HTTP注釋,它提供了請求的方法和相關的URL。

Retrofit内建了五個注釋:GET, POST, PUT, DELETE, and HEAD

相關的URL也由注釋來指定。

@GET("users/list")
           

還可以在URL中指定查詢參數。

@GET("users/list?sort=desc")
           

2、URL操縱

請求的URL可以被動态更新——在方法中使用塊或參數進行替代。替代塊是一個字母和數字組成的字元串,并使用大括号{}包圍。替代參數則必須使用@Path進行注釋,字元串同樣必須是字母和數字組成,并使用大括号{}包圍。

@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId);
           

可以添加查詢參數

@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);
           

對于更複雜的查詢參數,可以使用Map對象。

@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);
           

3、請求BODY

HTTP請求的Body可以使用@Body注釋進行指定。

@POST("users/new")
Call<User> createUser(@Body User user);
           

對象可以使用Retrofit示例指定的轉換器進行轉換。如果沒有添加轉換器,那麼就隻使用RequestBody。

4、表單編碼和MULTIPART

方法還可以聲明為表單編碼的資料或Multipart資料。

@FormEncoded注釋修飾方法時,表示發送的資料是表單編碼的資料。每一個鍵值對使用@Field注釋進行修飾。

@FormUrlEncoded
@POST("user/edit")
Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);
           

而Multipart請求則使用@Multipart注釋來修飾方法,多個部分使用@Part注釋進行修飾。

@Multipart
@PUT("user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);
           

5、HEADER操縱

可以使用@Headers注釋來為方法設定靜态的Header。

@Headers("Cache-Control: max-age=640000")
@GET("widget/list")
Call<List<Widget>> widgetList();
@Headers({
    "Accept: application/vnd.github.v3.full+json",
    "User-Agent: Retrofit-Sample-App"
})
@GET("users/{username}")
Call<User> getUser(@Path("username") String username);
           

要注意Header内容不會彼此覆寫,使用了同樣名字的Header内容都會包括到請求中。

請求的Header可以使用@Header注釋進行動态更新,相應的參數也必須在@Header中提供,如果值為null,Header可以省略。否則會調用toString方法。

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

Headers需要添加到每一個請求中,通過OkHttp攔截器進行指定。

五、同步與異步

Call執行個體可以以同步或異步的方式執行,每一個執行個體隻使用一次,但是調用clone()方法就會建立一個新執行個體,新執行個體也會使用。

在Android系統,主線程會執行回調;而在JVM中,在執行HTTP請求的同一個線程會發生回調。

Retrofit類通過你餓API接口來轉變成可回調的對象。

六、轉換器

預設情況下,Retrofit隻能反序列化HTTP Body為OkHttp的ResponseBody類型,它使用@Body接受RequestBody。

可以添加轉換器來支援其它類型。Retrofit提供了六個轉換器:

  • 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

下面是使用GsonConverterFactory類産生GitHubService接口的實作的示例,它使用Gson來反序列化。

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

繼續閱讀