github地址:https://github.com/jjxs/android-Retrofit.git
1.GET請(qǐng)求訪(fǎng)問(wèn)網(wǎng)絡(luò)
動(dòng)態(tài)配置URL地址:@Path
Retrofit提供了很多的請(qǐng)求參數(shù)注解,使得請(qǐng)求網(wǎng)路時(shí)更加便捷颜懊。在這里我們?nèi)耘f訪(fǎng)問(wèn)淘寶ip庫(kù)饭冬。其中揪阶,@Path用來(lái)動(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”唠梨,而用來(lái)替換{path}的正是需要傳入的 “String path”的值侥啤。接下來(lái)請(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”來(lái)替換 @GET注解中的{path}的值醉箕。
動(dòng)態(tài)指定查詢(xún)條件:@Query與@QueryMap
public interface IpServiceForQuery{
@GET("getIpInfo.php")
Call<IpModel> getIpMsg(@Query("ip")String ip);
}
但是在網(wǎng)絡(luò)請(qǐng)求中一般為了更精確的查找到我們所需要的數(shù)據(jù)讥裤,需要傳入很多的查詢(xún)參數(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)求訪(fǎng)問(wèn)網(wǎng)絡(luò)
傳輸數(shù)據(jù)類(lèi)型為鍵值對(duì):@Field
傳輸數(shù)據(jù)類(lèi)型為鍵值對(duì)荧关,這是我們最常用的POST請(qǐng)求數(shù)據(jù)類(lèi)型忍啤,淘寶ip庫(kù)支持?jǐn)?shù)據(jù)類(lèi)型為鍵值對(duì)的POST請(qǐng)求:
public interface IpServiceForPost {
@FormUrlEncoded
@POST("getIpInfo.php")
Call<IpModel> getIpMsg(@Field("ip") String first);
}
首先用到@FormUrlEncoded注解來(lái)標(biāo)明這是一個(gè)表單請(qǐng)求,然后在getIpMsg方法中使用@Field注解來(lái)標(biāo)示所對(duì)應(yīng)的String類(lèi)型數(shù)據(jù)的鍵鳄梅,從而組成一組鍵值對(duì)進(jìn)行傳遞戴尸。接下來(lái)請(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ù)類(lèi)型Json字符串:@Body
我們也可以用POST方式將Json字符串作為請(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ù)并不支持此類(lèi)型所以不會(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類(lèi)型可都,另一個(gè)參數(shù)是RequestBody類(lèi)型,它用來(lái)傳遞簡(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);
和單文件上傳是類(lèi)似的铣除,只是使用Map封裝了上傳的文件鹦付,并用@PartMap注解來(lái)標(biāo)示起來(lái)。其他的都一樣背苦,這里就不贅述了潘明。
3.消息報(bào)頭Header
Http請(qǐng)求中,為了防止攻擊或是過(guò)濾掉不安全的訪(fǎng)問(wèn)或是添加特殊加密的訪(fǎng)問(wèn)等等厚宰,用來(lái)減輕服務(wù)器的壓力和保證請(qǐng)求的安全遂填,通常都會(huì)在消息報(bào)頭中攜帶一些特殊的消息頭處理。Retrofit也提供了@Header來(lái)添加消息報(bào)頭撵幽。添加消息報(bào)頭有兩種方式盐杂,一種是靜態(tài)的,另一種是動(dòng)態(tài)的链烈,先來(lái)看靜態(tài)的方式,如下所示擦秽。
interface SomeService {
@GET("some/endpoint")
@Headers("Accept-Encoding: application/json")
Call<ResponseBody> getCarType();
}
使用@Headers注解添加消息報(bào)頭漩勤,如果想要添加多個(gè)消息報(bào)頭,則可以使用{}包含起來(lái):
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注解域蜗,可以通過(guò)調(diào)用getCarType方法來(lái)動(dòng)態(tài)的添加消息報(bào)頭噪猾。