1.Retrofit基本使用
首先來了解下Retrofit是什麼,在官網中對於Retrofit的描述是這樣的:
A type-safe HTTP client for Android and Java.
適用於Android和Java的類型安全的HTTP客戶端。
可以理解成一個封裝好的網絡請求庫。
接下來學習一下Retrofit的基本使用方法:
在app根目錄的build.gradle文件中加入依賴:
compile 'com.squareup.retrofit2:retrofit:2.3.0'
創建實體類:
我們使用http://www.kuaidi100.com/query?type=yuantong&postid=11111111111這個快遞接口來測試,根據返回數據創建實體類,類名爲PostInfo,在這裏就不貼代碼了,可以在文末下載Demo查看代碼。
定義請求參數接口:
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就是我們剛剛定義的實體類。參數中也使用了註解@Query,用於拼接傳入的字段(type=yuantong&postid=11111111111)。
網絡請求:
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,由於返回的數據是json類型的,還需要添加轉換工廠類,這需要在build.gradle文件中加入依賴:
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
然後調用Retrofit的create方法創建RetrofitService的實體類,得到實體類之後就可以調用其中的getPostInfo方法並傳入參數,getPostInfo方法會返回一個Call實體類,接着調用Call的enqueue方法,傳入Callback回調,重寫onResponse(請求成功回調)和onFailure(請求失敗回調)方法,response參數中包含了請求結果中的所有信息(body、code、headers等)。
OK,到這裏Retrofit的基本用法就講完了,接下來我們來了解一下Retrofit的其他用法。
2.Retrofit更多用法
請求方法
在RetrofitService的getPostInfo方法中,我們使用了@GET註解,說明這是一個GET方法,當然也可以寫成HTTP協議中的其他請求方法(比如POST、PUT、DELETE、HEAD等)。
請求參數
在getPostInfo方法的參數中使用了@Query註解,除此之外還可以使用@QueryMap、@Path、@Body、@FormUrlEncoded/@Field、@Multipart/@Part、@Header/@Headers。
- @Query()
@GET("query")
Call<PostInfo> getPostInfo(@Query("type") String type, @Query("postid") String postid);
相當於
@GET(query?type=type&postid=postid)
Call<PostInfo> getPostInfo(@Query("type") String type, @Query("postid") String postid);
- @QueryMap
當參數很多的時候可以使用Map集合:
@GET("query")
Call<Book> getSearchBook(@QueryMap Map<String, String> parameters);
- @Path
用於替換url中的某些字段,當url中字段不確定時可以使用:
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId);
id可以爲任意字段,需要和@Path(“id”)中的字段保持一致,如果需要請求參數,也可以使用@Query拼接:
@GET("group/{id}/users")
Call<List<User>> groupList(@Path("id") int groupId, @Query("sort") String sort);
- @Body
可以使用實體類作爲請求體,Retrofit會幫我們自動轉換:
@POST("users/new")
Call<User> createUser(@Body User user);
- @FormUrlEncoded/@Field
用於傳送表單數據,注意在頭部需要加上@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
用於設置請求頭:
@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)
也可以通過@Headers設置:
@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);
轉換器
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結合使用
如果你對RxJava還不太瞭解,可以看下這篇文章《給 Android 開發者的 RxJava 詳解》。
首先在build.gradle文件中加入依賴:
compile 'com.squareup.retrofit2:adapter-rxjava:2.3.0'
compile 'io.reactivex:rxandroid:1.2.1'
將RetrofitService類中getPostInfo方法的返回值修改爲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);
}
在創建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()) // 在子線程中進行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中,由於鏈式調用的影響,是被觀察者訂閱觀察者。
到這裏Retrofit + RxJava結合使用就講完了,由於Retrofit、RxJava屬於同門師兄弟,結合使用還是很容易的。
4.Retrofit打印請求參數
Retrofit中無法打印請求參數,由於Retrofit是基於OkHttp進行封裝的,可以對OkHttp添加日誌攔截器來打印請求參數:
在build.gradle文件中加入依賴:
compile 'com.squareup.okhttp3:logging-interceptor:3.8.0'
OkHttp添加攔截器:
public class RetrofitUtils {
/**
* 獲取OkHttpClient
* 用於打印請求參數
*
* @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請求參數:", message);
}
});
loggingInterceptor.setLevel(level);
// 定製OkHttp
OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
// OkHttp進行添加攔截器loggingInterceptor
httpClientBuilder.addInterceptor(loggingInterceptor);
return httpClientBuilder.build();
}
}
將定製的OkHttpClient添加到Retrofit中:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constant.SERVER_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(RetrofitUtils.getOkHttpClient()) // 打印請求參數
.build();
大功告成!
5.寫在最後
源碼已託管到GitHub上,歡迎Fork,覺得還不錯就Start一下吧!
歡迎同學們吐槽評論,如果你覺得本篇博客對你有用,那麼就留個言或者頂一下吧(^-^)
在下篇文章中將會探討一下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'