
1.Retrofit基本使用
首先來了解下Retrofit是什么,在官網(wǎng)中對于Retrofit的描述是這樣的:
A type-safe HTTP client for Android and Java.
適用于Android和Java的類型安全的HTTP客戶端。
可以理解成一個封裝好的網(wǎng)絡(luò)請求庫。
接下來學(xué)習(xí)一下Retrofit的基本使用方法:
在app根目錄的build.gradle文件中加入依賴:
compile 'com.squareup.retrofit2:retrofit:2.3.0'
創(chuàng)建實(shí)體類:
我們使用http://www.kuaidi100.com/query?type=yuantong&postid=11111111111 這個快遞接口來測試,根據(jù)返回?cái)?shù)據(jù)創(chuàng)建實(shí)體類,類名為PostInfo,在這里就不貼代碼了,可以在文末下載Demo查看代碼。
定義請求參數(shù)接口:
public interface RetrofitService {
/**
* 獲取快遞信息
*
* @param type 快遞類型
* @param postid 快遞單號
* @return Call<PostInfo>
*/
@GET("query")
Call<PostInfo> getPostInfo(@Query("type") String type, @Query("postid") String postid);
}
定義一個接口RetrofitService,和普通的接口類相同,在里面定義一個方法getPostInfo,可以看到這個方法使用了@GET("query")注解,代表這是一個GET請求,請求接口為query(完整請求地址中域名/到?之間的字段),方法返回值為Call<PostInfo>實(shí)體,這個稍后會用于具體的網(wǎng)絡(luò)請求,PostInfo就是我們剛剛定義的實(shí)體類。參數(shù)中也使用了注解@Query,用于拼接傳入的字段(type=yuantong&postid=11111111111)。
網(wǎng)絡(luò)請求:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.kuaidi100.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
RetrofitService service = retrofit.create(RetrofitService.class);
Call<PostInfo> call = service.getPostInfo("yuantong", "11111111111");
call.enqueue(new Callback<PostInfo>() {
@Override
public void onResponse(Call<PostInfo> call, Response<PostInfo> response) {
Log.i("http返回:", response.body().toString() + "");
}
@Override
public void onFailure(Call<PostInfo> call, Throwable t) {
}
});
可以看到Retrofit使用了Builder模式,首先傳入baseUrl,由于返回的數(shù)據(jù)是json類型的,還需要添加轉(zhuǎn)換工廠類,這需要在build.gradle文件中加入依賴:
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
然后調(diào)用Retrofit的create方法創(chuàng)建RetrofitService的實(shí)體類,得到實(shí)體類之后就可以調(diào)用其中的getPostInfo方法并傳入?yún)?shù),getPostInfo方法會返回一個Call實(shí)體類,接著調(diào)用Call的enqueue方法,傳入Callback回調(diào),重寫onResponse(請求成功回調(diào))和onFailure(請求失敗回調(diào))方法,response參數(shù)中包含了請求結(jié)果中的所有信息(body、code、headers等)。
OK,到這里Retrofit的基本用法就講完了,接下來我們來了解一下Retrofit的其他用法。
2.Retrofit更多用法
請求方法
在RetrofitService的getPostInfo方法中,我們使用了@GET注解,說明這是一個GET方法,當(dāng)然也可以寫成HTTP協(xié)議中的其他請求方法(比如POST、PUT、DELETE、HEAD等)。
請求參數(shù)
在getPostInfo方法的參數(shù)中使用了@Query注解,除此之外還可以使用@QueryMap、@Path、@Body、@FormUrlEncoded/@Field、@Multipart/@Part、@Header/@Headers。
- @Query()
@GET("query")
Call<PostInfo> getPostInfo(@Query("type") String type, @Query("postid") String postid);
相當(dāng)于
@GET(query?type=type&postid=postid)
Call<PostInfo> getPostInfo(@Query("type") String type, @Query("postid") String postid);
- @QueryMap
當(dāng)參數(shù)很多的時候可以使用Map集合:
@GET("query")
Call<Book> getSearchBook(@QueryMap Map<String, String> parameters);
- @Path
用于替換url中的某些字段,當(dāng)url中字段不確定時可以使用:
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId);
id可以為任意字段,需要和@Path("id")中的字段保持一致,如果需要請求參數(shù),也可以使用@Query拼接:
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);
- @Body
可以使用實(shí)體類作為請求體,Retrofit會幫我們自動轉(zhuǎn)換:
@POST("users/new")
Call<User> createUser(@Body User user);
- @FormUrlEncoded/@Field
用于傳送表單數(shù)據(jù),注意在頭部需要加上@FormUrlEncoded,first_name代表key,first代表value:
@FormUrlEncoded
@POST("user/edit")
Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);
- @Multipart/@Part
用于上傳文件:
@Multipart
@PUT("user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);
- @Header/@Headers
用于設(shè)置請求頭:
@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)
也可以通過@Headers設(shè)置:
@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);
轉(zhuǎn)換器
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
3.Retrofit + RxJava結(jié)合使用
如果你對RxJava還不太了解,可以看下這篇文章《給 Android 開發(fā)者的 RxJava 詳解》。
首先在build.gradle文件中加入依賴:
compile 'com.squareup.retrofit2:adapter-rxjava:2.3.0'
compile 'io.reactivex:rxandroid:1.2.1'
將RetrofitService類中g(shù)etPostInfo方法的返回值修改為Observable(被觀察者):
public interface RetrofitService {
/**
* 獲取快遞信息
* Rx方式
*
* @param type 快遞類型
* @param postid 快遞單號
* @return Observable<PostInfo>
*/
@GET("query")
Observable<PostInfo> getPostInfoRx(@Query("type") String type, @Query("postid") String postid);
}
在創(chuàng)建Retrofit時添加RxJava支持:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.kuaidi100.com/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 支持RxJava
.build();
獲取被觀察者:
RetrofitService service = retrofit.create(RetrofitService.class);
Observable<PostInfo> observable = service.getPostInfoRx("yuantong", "11111111111");
訂閱:
observable.subscribeOn(Schedulers.io()) // 在子線程中進(jìn)行Http訪問
.observeOn(AndroidSchedulers.mainThread()) // UI線程處理返回接口
.subscribe(new Observer<PostInfo>() { // 訂閱
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(PostInfo postInfo) {
Log.i("http返回:", postInfo.toString() + "");
}
});
在RxJava中,由于鏈?zhǔn)秸{(diào)用的影響,是被觀察者訂閱觀察者。
到這里Retrofit + RxJava結(jié)合使用就講完了,由于Retrofit、RxJava屬于同門師兄弟,結(jié)合使用還是很容易的。
4.Retrofit打印請求參數(shù)
Retrofit中無法打印請求參數(shù),由于Retrofit是基于OkHttp進(jìn)行封裝的,可以對OkHttp添加日志攔截器來打印請求參數(shù):
在build.gradle文件中加入依賴:
compile 'com.squareup.okhttp3:logging-interceptor:3.8.0'
OkHttp添加攔截器:
public class RetrofitUtils {
/**
* 獲取OkHttpClient
* 用于打印請求參數(shù)
*
* @return OkHttpClient
*/
public static OkHttpClient getOkHttpClient() {
// 日志顯示級別
HttpLoggingInterceptor.Level level = HttpLoggingInterceptor.Level.BODY;
// 新建log攔截器
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(String message) {
Log.i("Http請求參數(shù):", message);
}
});
loggingInterceptor.setLevel(level);
// 定制OkHttp
OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
// OkHttp進(jìn)行添加攔截器loggingInterceptor
httpClientBuilder.addInterceptor(loggingInterceptor);
return httpClientBuilder.build();
}
}
將定制的OkHttpClient添加到Retrofit中:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constant.SERVER_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(RetrofitUtils.getOkHttpClient()) // 打印請求參數(shù)
.build();
大功告成!
5.寫在最后
源碼已托管到GitHub上,歡迎Fork,覺得還不錯就Start一下吧!
歡迎同學(xué)們吐槽評論,如果你覺得本篇博客對你有用,那么就留個言或者點(diǎn)下喜歡吧(^-^)
在下篇文章中將會探討一下Retrofit封裝的最佳姿勢,敬請期待!
已修改為支持RxJava2,最新代碼已同步至GitHub。
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0'
compile 'com.squareup.okhttp3:logging-interceptor:3.8.0'
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'