前言
在上一篇Android網(wǎng)絡(luò)編程(九)Retrofit2前篇[基本使用]中我們了解了Retrofit的最基本的GET方式訪問網(wǎng)絡(luò)的寫法以及請(qǐng)求參數(shù)的簡(jiǎn)單介紹暖璧。這一篇我們來詳細(xì)的了解Retrofit的請(qǐng)求參數(shù)。
1.GET請(qǐng)求訪問網(wǎng)絡(luò)
動(dòng)態(tài)配置URL地址:@Path
Retrofit提供了很多的請(qǐng)求參數(shù)注解,使得請(qǐng)求網(wǎng)路時(shí)更加便捷。在這里我們?nèi)耘f訪問淘寶ip庫(kù)。其中愤惰,@Path用來動(dòng)態(tài)的配置URL地址。請(qǐng)求網(wǎng)絡(luò)接口代碼如下所示赘理。
public interface IpServiceForPath {
@GET("{path}/getIpInfo.php?ip=59.108.54.37")
Call<IpModel> getIpMsg(@Path("path") String path);
}
在GET注解中包含了{(lán)path}宦言,它對(duì)應(yīng)著@Path注解中的"path",而用來替換{path}的正是需要傳入的 "String path"的值商模。接下來請(qǐng)求網(wǎng)絡(luò)的代碼如下所示奠旺。
String url = "http://ip.taobao.com/";
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
IpServiceForPath ipService = retrofit.create(IpServiceForPath.class);
Call<IpModel>call=ipService.getIpMsg("service");//1
call.enqueue(new Callback<IpModel>() {
@Override
public void onResponse(Call<IpModel> call, Response<IpModel> response) {
String country= response.body().getData().getCountry();
Toast.makeText(getApplicationContext(),country,Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(Call<IpModel> call, Throwable t) {
}
});
在注釋1處蜘澜,傳入"service"來替換 @GET注解中的{path}的值。
動(dòng)態(tài)指定查詢條件:@Query與@QueryMap
在上一篇中我們用@Query來動(dòng)態(tài)的替換ip地址為了能更方便的得到該ip所對(duì)應(yīng)的地理信息:
public interface IpServiceForQuery{
@GET("getIpInfo.php")
Call<IpModel> getIpMsg(@Query("ip")String ip);
}
但是在網(wǎng)絡(luò)請(qǐng)求中一般為了更精確的查找到我們所需要的數(shù)據(jù)响疚,需要傳入很多的查詢參數(shù)鄙信,如果用@Query會(huì)比較麻煩,這時(shí)我們可以采用@QueryMap忿晕,將所有的參數(shù)集成在一個(gè)Map統(tǒng)一傳遞:
public interface IpServiceForQueryMap {
@GET("getIpInfo.php")
Call<IpModel> getIpMsg(@QueryMap Map<String, String> options);
}
2.POST請(qǐng)求訪問網(wǎng)絡(luò)
傳輸數(shù)據(jù)類型為鍵值對(duì):@Field
傳輸數(shù)據(jù)類型為鍵值對(duì)装诡,這是我們最常用的POST請(qǐng)求數(shù)據(jù)類型,淘寶ip庫(kù)支持?jǐn)?shù)據(jù)類型為鍵值對(duì)的POST請(qǐng)求:
public interface IpServiceForPost {
@FormUrlEncoded
@POST("getIpInfo.php")
Call<IpModel> getIpMsg(@Field("ip") String first);
}
首先用到@FormUrlEncoded注解來標(biāo)明這是一個(gè)表單請(qǐng)求践盼,然后在getIpMsg方法中使用@Field注解來標(biāo)示所對(duì)應(yīng)的String類型數(shù)據(jù)的鍵鸦采,從而組成一組鍵值對(duì)進(jìn)行傳遞。接下來請(qǐng)求網(wǎng)絡(luò)的代碼如下所示咕幻。
String url = "http://ip.taobao.com/service/";
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
IpServiceForPost ipService = retrofit.create(IpServiceForPost.class);
Call<IpModel>call=ipService.getIpMsg("59.108.54.37");
call.enqueue(new Callback<IpModel>() {
@Override
public void onResponse(Call<IpModel> call, Response<IpModel> response) {
String country= response.body().getData().getCountry();
Toast.makeText(getApplicationContext(),country,Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(Call<IpModel> call, Throwable t) {
}
});
傳輸數(shù)據(jù)類型Json字符串:@Body
我們也可以用POST方式將Gson字符串作為請(qǐng)求體發(fā)送到服務(wù)器渔伯,請(qǐng)求網(wǎng)絡(luò)接口代碼為:
public interface IpServiceForPostBody {
@POST("getIpInfo.php")
Call<IpModel> getIpMsg(@Body Ip ip);
}
用@Body這個(gè)注解標(biāo)識(shí)參數(shù)對(duì)象即可,retrofit會(huì)將Ip對(duì)象轉(zhuǎn)換為字符串谅河。
public class Ip {
private String ip;
public Ip(String ip) {
this.ip = ip;
}
}
請(qǐng)求網(wǎng)絡(luò)的代碼基本上都是一致的:
String url = "http://ip.taobao.com/service/";
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
IpServiceForPostBody ipService = retrofit.create(IpServiceForPostBody.class);
Call<IpModel>call=ipService.getIpMsg(new Ip(ip));
call.enqueue(new Callback<IpModel>() {
@Override
public void onResponse(Call<IpModel> call, Response<IpModel> response) {
String country= response.body().getData().getCountry();
Log.i("wangshu","country"+country);
Toast.makeText(getApplicationContext(),country,Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(Call<IpModel> call, Throwable t) {
}
});
}
運(yùn)行程序用Fiddler抓包咱旱,如下圖所示确丢。
可以看到請(qǐng)求數(shù)據(jù)是一個(gè)Json字符串绷耍,因?yàn)樘詫歩p庫(kù)并不支持此類型所以不會(huì)返回我們需要的地理信息數(shù)據(jù)。
單個(gè)文件上傳:@Part
public interface UploadFileForPart {
@Multipart
@POST("user/photo")
Call<User> updateUser(@Part MultipartBody.Part photo, @Part("description") RequestBody description);
}
Multipart注解表示允許多個(gè)@Part鲜侥,updateUser方法第一個(gè)參數(shù)是準(zhǔn)備上傳的圖片文件褂始,使用了MultipartBody.Part類型,另一個(gè)參數(shù)是RequestBody類型描函,它用來傳遞簡(jiǎn)單的鍵值對(duì)崎苗。請(qǐng)求網(wǎng)絡(luò)代碼如下所示。
...
File file = new File(Environment.getExternalStorageDirectory(), "wangshu.png");
RequestBody photoRequestBody = RequestBody.create(MediaType.parse("image/png"), file);
MultipartBody.Part photo = MultipartBody.Part.createFormData("photos", "wangshu.png", photoRequestBody);
UploadFileForPart uploadFile = retrofit.create(UploadFileForPart.class);
Call<User> call = uploadFile.updateUser(photo, RequestBody.create(null, "wangshu"));
...
多個(gè)文件上傳:@PartMap
@Multipart
@POST("user/photo")
Call<User> updateUser(@PartMap Map<String, RequestBody> photos, @Part("description") RequestBody description);
和單文件上傳是類似的舀寓,只是使用Map封裝了上傳的文件胆数,并用@PartMap注解來標(biāo)示起來。其他的都一樣互墓,這里就不贅述了必尼。
**3.消息報(bào)頭Header **
Http請(qǐng)求中,為了防止攻擊或是過濾掉不安全的訪問或是添加特殊加密的訪問等等篡撵,用來減輕服務(wù)器的壓力和保證請(qǐng)求的安全判莉,通常都會(huì)在消息報(bào)頭中攜帶一些特殊的消息頭處理。Retrofit也提供了@Header來添加消息報(bào)頭育谬。添加消息報(bào)頭有兩種方式券盅,一種是靜態(tài)的,另一種是動(dòng)態(tài)的膛檀,先來看靜態(tài)的方式锰镀,如下所示娘侍。
interface SomeService {
@GET("some/endpoint")
@Headers("Accept-Encoding: application/json")
Call<ResponseBody> getCarType();
}
使用@Headers注解添加消息報(bào)頭,如果想要添加多個(gè)消息報(bào)頭互站,則可以使用{}包含起來:
interface SomeService {
@GET("some/endpoint")
@Headers({
"Accept-Encoding: application/json",
"User-Agent: MoonRetrofit"
})
Call<ResponseBody> getCarType();
}
動(dòng)態(tài)的方式添加消息報(bào)頭如下所示私蕾。
interface SomeService {
@GET("some/endpoint")
Call<ResponseBody> getCarType(
@Header("Location") String location);
}
使用@Header注解,可以通過調(diào)用getCarType方法來動(dòng)態(tài)的添加消息報(bào)頭胡桃。