2015-03-29 12:00
最近將Android項目的網(wǎng)絡(luò)連接庫切換到了Retrofit 2.0,以前用的Volley。
使用Retrofit后接口更加接近RESTful風(fēng)格。邏輯更加清晰,更加靈活。
基本使用
定義接口:
新建一個Service接口類,在該類中聲明要調(diào)用的接口。
例如:
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
@GET 表示該接口是用HTTP GET調(diào)用,GET后面的括號里面是該接口的Endpoint(主機(jī)后面的地址)。
@Path 是用來動態(tài)替換URL中的字段的{}的部分,用來動態(tài)生成URL.
POST方式:
@POST("users/new")
Call<User> createUser(@Body User user);
@Body 請求的body,Retrofit會自動用配置的格式轉(zhuǎn)換器將User對象轉(zhuǎn)化為對用的格式(如JSON,XML等)
@FormUrlEncoded
@POST("user/edit")
Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);
post提交form形式,@FormUrlEncoded 表示該請求的body是Form-encoded數(shù)據(jù)。@Field就是form的字段名稱。
Map:
@ormUrlEncoded
@POST("/some/endpoint")
Call<SomeResponse> someEndpoint(@FieldMap Map<String, String> names);
多參數(shù)表單數(shù)據(jù):
@Multipart
@PUT("user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);
設(shè)置請求Header:
@Headers({
"Accept: application/vnd.github.v3.full+json",
"User-Agent: Retrofit-Sample-App"
})
@GET("users/{username}")
Call<User> getUser(@Path("username") String username);
接口調(diào)用
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
GitHubService service = retrofit.create(GitHubService.class);
Call<List<Repo>> call = service.listRepos("user");
創(chuàng)建一個Retrofit對象,創(chuàng)建的時候要指定BaseUrl和數(shù)據(jù)格式轉(zhuǎn)換器。數(shù)據(jù)格式轉(zhuǎn)換器用來將請求的對象轉(zhuǎn)換為對用的數(shù)據(jù)格式。例如配置GsonConverterFactory,則會將請求中的對象轉(zhuǎn)換為JSON字符串,將響應(yīng)中的JSON字符串轉(zhuǎn)換為對象。
Retrofit支持的轉(zhuǎn)換器:
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
你也可以自定義一個轉(zhuǎn)換器,例如:
private static class RawJsonConverterFactory extends Converter.Factory {
public static RawJsonConverterFactory create() {
return new RawJsonConverterFactory();
}
@Override
public Converter<?, RequestBody> toRequestBody(Type type, Annotation[] annotations) {
return super.toRequestBody(type, annotations);
}
@Override
public Converter<ResponseBody, ?> fromResponseBody(Type type, Annotation[] annotations) {
return new RawJsonResponseBodyConverter();
}
}
private static class RawJsonResponseBodyConverter<String> implements Converter<ResponseBody, String> {
public RawJsonResponseBodyConverter() {
}
@Override
public String convert(ResponseBody value) throws IOException {
return (String) value.string();
}
}
接口調(diào)用后返回一個Call<?>對象,call的泛型就是接口數(shù)據(jù)轉(zhuǎn)換后的對象。Call可以指定該次請求同步還是異步。
同步:
Response<List<Repo>> response = call.execute();
同步調(diào)用接口直接返回一個Response對象,Response包含響應(yīng)的所有數(shù)據(jù):響應(yīng)碼(the reponse code),響應(yīng)消息(the response message),以及讀取相應(yīng)頭(headers)和body;Body就是接口返回的最終數(shù)據(jù)。
異步:
call.enqueue(new Callback<List<Repo>>() {
@Override void onResponse(/* ... */) {
// ...
}
@Override void onFailure(Throwable t) {
// ...
}
});
異步要傳一個接口回調(diào)接口,接口包含請求成功和失敗的方法回調(diào)。
打印Log和設(shè)置Timeout
由于請求和響應(yīng)在Retrofit中直接轉(zhuǎn)換處理了,Retrofit中又沒暴漏出來可以打印URL和請求Body的方法,所以打印Log就沒那么直接了。解決方案:
指定HTTPClent,在HTTPClient中使用攔截器打印Log.
Retrofit默認(rèn)使用的是OkHttp,當(dāng)然你也可以使用別的Http Client.
OkHttpClient client = new OkHttpClient();
client.setConnectTimeout(30, TimeUnit.SECONDS); //連接超時
client.setReadTimeout(30,TimeUnit.SECONDS); //讀取數(shù)據(jù)超時
client.setWriteTimeout(10,TimeUnit.SECONDS); //發(fā)送數(shù)據(jù)超時
//Log攔截器,打印請求和響應(yīng)的LOG
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BASIC);
client.interceptors().add(logging);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.client(client) //設(shè)置Client
.build();
Log的Level有4個級別:NONE,BASIC,HEADERS,BODY
NONE:不打印Log
BASIC: 只打印請求和響應(yīng)的基本信息
HEADERS:打印基本信息和頭信息
BODY:打印請求和響應(yīng)的所有信息
多converter
Retrofit可以配置多個轉(zhuǎn)換器,如可以同時設(shè)置JSON和XML的轉(zhuǎn)換器,Retrofit會使用配置的所有的converter對數(shù)據(jù)進(jìn)行轉(zhuǎn)換。
所以添加 converter 的順序很重要,
例如:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create())
.addConverterFactory(ProtoConverterFactory.create())
.build();
設(shè)置了一個Gson轉(zhuǎn)換器和一個Proto轉(zhuǎn)換器,按照配置的順序,Retrofit會依次詢問每個converter能否處理數(shù)據(jù),直到數(shù)據(jù)被處理了或試過了所有的轉(zhuǎn)換器。