0. Thanks To
Retrofit使用詳解(一)
Android Retrofit 2.0 的詳細 使用攻略(含實例講解)
Android Retrofit網(wǎng)絡(luò)請求Service,@Path、@Query羹铅、@QueryMap、@Map...
1.目錄
- 簡介
- 依賴
- GET
- POST
2.簡介
可以說壤蚜,Retrofit是當(dāng)下最快,效率最高的Http請求框架,他有如下的特點:
Retrofit 是一個 RESTful 的 HTTP 網(wǎng)絡(luò)請求框架的封裝省艳。(RESTful??可以百度百度這里不作討論)
Retrofit 其實是一個高度封裝的框架亲茅,其底層用的是Okhttp
其工作流程大致如下:
- Retrofit 所做的回铛,緊緊是把我們的一些接口參數(shù),請求方法組裝克锣,然后交給Okhttp去執(zhí)行茵肃。
3.依賴
樓主寫這篇文章的時候:(2018年1月21日18:15:57),最新的版本如下:
因為解析數(shù)據(jù)是JSON袭祟,這里還添加了Gson簡析工廠
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
4.GET
Retrofit 通過注解形式验残,去聲明參數(shù),和請求方法巾乳。我們先看看該怎么正確地根據(jù)API去聲明一個借口您没。
假如API是:
http://abc.cn:8080/Market/getAppList?pageIndex=0&pageSize=8
,抽離服務(wù)器項目地址:http://abc.cn:8080/Market/
后胆绊,有兩個參數(shù)氨鹏,那么你應(yīng)該這樣聲明接口:
public interface GetAppList {
@GET("getAppList")
Call<AppListBean> get(@Query("pageIndex") int pageIndex, @Query("pageSize") int pageSize);
}
使用的是@Query
注解聲明參數(shù),@GET("getAppList")
聲明的是相對地址压状。
- 假如API是:
http://abc.cn:8080/Market/{userId}/getAppList
變化的是API中的一部分仆抵,如:
http://abc.cn:8080/Market/123/getAppList
http://abc.cn:8080/Market/246/getAppList
http://abc.cn:8080/Market/468/getAppList
同樣,抽離服務(wù)器項目地址:http://abc.cn:8080/Market/
种冬,聲明接口:
public interface GetAppList {
@GET("{userId}/getAppList")
Call<AppListBean> get(@Path("userId") int userId);
}
使用@Path
聲明替換API的Path路徑镣丑。
- 有了接口,就可以請求數(shù)據(jù):
//拼裝接口
Retrofit retrofit = new Retrofit.Builder()
//設(shè)置網(wǎng)絡(luò)請求的 Base Url地址
.baseUrl("http://abc.cn:8080/Market/")
//設(shè)置數(shù)據(jù)解析器
.addConverterFactory(GsonConverterFactory.create())
.build();
// 創(chuàng)建 網(wǎng)絡(luò)請求接口 的實例
GetAppList request = retrofit.create(GetAppList.class);
//創(chuàng)建請求娱两,傳入?yún)?shù)
Call<AppListBean> call = request.get(1,8);
//異步請求
call.enqueue(new Callback<AppListBean>() {
@Override
public void onResponse(Call<AppListBean> call, Response<AppListBean> response) {
}
@Override
public void onFailure(Call<AppListBean> call, Throwable t) {
}
});
抽離的服務(wù)器項目地址http://abc.cn:8080/Market/
應(yīng)該在創(chuàng)建請求的的時候通過Retrofit.Builder().baseUrl傳入莺匠。注意的是,baseUrl必須以/
結(jié)尾十兢,不然拋異常趣竣。
上面返回的JSON摇庙,Mapping后的Bean是AppListBean,直接使用插件生成即可期贫。
-
Call<T>
是具體的請求實例跟匆,泛型是請求回來的數(shù)據(jù)Bean。
2.png enqueue通砍,執(zhí)行請求玛臂,有異步的和同步的。
cancel封孙,取消執(zhí)行迹冤。
clone,深復(fù)制虎忌。
-
Response<T>
是結(jié)果體
3.jpg message泡徙,請求返回的結(jié)果信息。
isSuccessful膜蠢,是否成功堪藐。
code,請求的結(jié)果碼挑围,200是成功礁竞。
body,就是泛型
T
的實體杉辙,注意判空模捂。
再列舉其他的情況:
- newsId參數(shù)一個,type參數(shù)個數(shù)不確定
http://api.stay4it.com/News?newsId=1&type=類型1…
http://api.stay4it.com/News?newsId={資訊id}&type={類型1}&type={類型2}…
這樣:
@GET("News")
Call<NewsBean> getItem(@QueryMap Map<String, String> map);
或者:
@GET("News")
Call<NewsBean> getItem(
@Query("newsId") String newsId蜘矢,
@QueryMap Map<String, String> map);
5.POST
上面敘述了GET和其他一些基礎(chǔ)的東西狂男。POST就來更直接的。
- POST 一個字段
@POST("mobile/register")
Call<ResponseBody> registerDevice(@Field("id") String registerid);
@Field
聲明字段的key
- POST 兩個及兩個以上的字段
http://xxx/api/Comments
@FormUrlEncoded
@POST("Comments/{newsId}")
Call<Comment> reportComment(
@Path("newsId") String commentId,
@Field("reason") String reason);
@FormUrlEncoded
表示請求發(fā)送編碼表單數(shù)據(jù)品腹,每個鍵值對需要使用@Field注解
- POST URL不完整岖食,需要補全,使用
@Path
http://xxx/api/Comments/1?access_token=1234123
http://xxx/api/Comments/{newsId}?access_token={access_token}
@FormUrlEncoded
@POST("Comments/{newsId}")
Call<Comment> reportComment(
@Path("newsId") String commentId,
@Query("access_token") String access_token,
@Field("reason") String reason);
這個API還需要拼接一個newsId及一個Token舞吭,分別使用@Path
和@Query
聲明
- POST 對象(JSON)
@POST("mobile/register")
Call register1(@Body RegisterPost post);
@Body
聲明對象县耽,Retrofit會自動序列化成JSON,序列化使用的庫镣典,通過:
.addConverterFactory(GsonConverterFactory.create())
聲明。
- POST 文件(圖片唾琼,MP3兄春,等等)
public interface FileUploadService {
@Multipart
@POST("upload")
Call<ResponseBody> upload(@Part("description") RequestBody description,
@Part MultipartBody.Part file);
}
而他的請求寫法也有點不一樣:
// 創(chuàng)建 RequestBody,用于封裝構(gòu)建RequestBody
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
// MultipartBody.Part 和后端約定好Key锡溯,這里的partName是用image
MultipartBody.Part body = MultipartBody.Part.createFormData("image", file.getName(), requestFile);
// 添加描述
String descriptionString = "hello, 這是文件描述";
RequestBody description = RequestBody.create(MediaType.parse("multipart/form-data"), descriptionString);
// 執(zhí)行請求
Call<ResponseBody> call = service.upload(description, body);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call,
Response<ResponseBody> response) {
Log.v("Upload", "success");
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.e("Upload error:", t.getMessage());
}
});
}