這部分主要是實現(xiàn)Retrofit的轉換器使用檀何,以及實現(xiàn)cookies緩存+嵌套請求蝇裤,文件的上傳和下載
- 相關依賴
implementation'com.squareup.retrofit2:retrofit:2.9.0'
implementation'com.squareup.retrofit2:converter-gson:2.9.0'
implementation'com.google.code.gson:gson:2.8.6'
implementation "com.squareup.retrofit2:adapter-rxjava3:2.9.0"
1、使用轉換器
和前面一樣频鉴,也是要創(chuàng)建請求的接口:
public interface WanAndroidService {
//不使用轉換器猖辫,直接使用Gson來轉換
@POST("user/login")
@FormUrlEncoded
Call<ResponseBody> loginWanAndroid(@Field("username") String username,@Field("password") String password);
//使用轉換器,ResponseBody只能得到字符串,用轉換器轉換成Bean對象
@POST("user/login")
@FormUrlEncoded
Call<WanAndroidBean> loginWanAndroid2(@Field("username") String username,@Field("password") String password);
}
接著在Java環(huán)境中創(chuàng)建對應的測試單元(對應的WanAndroidBean .java可以用PostMan配合GsonFormat插件自動生成):
//retrofit轉換器測試
public class WandroidUnitTest {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://www.wanandroid.com/")
.build();
WanAndroidService wanAndroidService = retrofit.create(WanAndroidService.class);
@Test
public void loginTest(){
Call<ResponseBody> call = wanAndroidService.loginWanAndroid("用戶名", "密碼");
try {
Response<ResponseBody> response = call.execute();
String result = response.body().string();
//第一種砚殿;使用Gson手動轉換
//將Json字符串轉換成對應的對象
WanAndroidBean wanAndroidBean = new Gson().fromJson(result,WanAndroidBean.class);
System.out.println(wanAndroidBean.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void addConvertLoginTest(){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://www.wanandroid.com/")
//第二種:添加轉換器啃憎,讓Retrofit自動轉換,使用GsonConvertFactory將json數(shù)據(jù)轉換成對象
.addConverterFactory(GsonConverterFactory.create())
.build();
WanAndroidService wanAndroidService = retrofit.create(WanAndroidService.class);
Call<WanAndroidBean> wanAndroidBeanCall = wanAndroidService.loginWanAndroid2("用戶名", "密碼");
try {
Response<WanAndroidBean> beanResponse = wanAndroidBeanCall.execute();
WanAndroidBean wanAndroidBean = beanResponse.body();
System.out.println(wanAndroidBean);
} catch (IOException e) {
e.printStackTrace();
}
}
2似炎、使用嵌套請求+cookies緩存
嵌套請求是指在請求有順序的情況下辛萍,例如必須要先登錄再獲取文章列表,有先后順序羡藐,
- 封裝請求的接口
public interface WanAndroidService {
//使用適配器贩毕,與Rxjava聯(lián)合使用
@POST("user/login")
@FormUrlEncoded
Flowable<WanAndroidBean> login2(@Field("username")String username,@Field("password")String password);
//請求文章列表
@GET("lg/collect/list/{pageNum}/json")
Flowable<ResponseBody> getArticle(@Path("pageNum")int pageNum);
}
- 實際請求,這里加入了Rxjava的轉換器
//使用適配器仆嗦,實現(xiàn)嵌套請求
Map<String,List<Cookie>> cookies = new HashMap<>();
@Test
public void useAdapter(){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://www.wanandroid.com/")
//配置Cookie緩存
.callFactory(new OkHttpClient.Builder().cookieJar(new CookieJar() {
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> list) {
cookies.put(url.host(),list);
}
@Override
public List<Cookie> loadForRequest(HttpUrl url) {
List<Cookie> cookies = WandroidUnitTest.this.cookies.get(url.host());
return cookies == null ? new ArrayList<>():cookies;
}
}).build())
//第二種:添加轉換器辉阶,讓Retrofit自動轉換,使用GsonConvertFactory將json數(shù)據(jù)轉換成對象
.addConverterFactory(GsonConverterFactory.create())
//添加適配器,讓它不再是單一的Call對象,改為Rxjava的Flowable對象
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.build();
WanAndroidService wanAndroidService = retrofit.create(WanAndroidService.class);
//使用的是Rxjava的線程切換調(diào)用
//1.先登錄
wanAndroidService.login2("用戶名", "密碼")
//生成一個新的publish
.flatMap(new Function<WanAndroidBean, Publisher<ResponseBody>>() {
@Override
public Publisher<ResponseBody> apply(WanAndroidBean wanAndroidBean) throws Throwable {
//2.嵌套請求谆甜,請求文章列表
return wanAndroidService.getArticle(0);
}
})
.observeOn(Schedulers.io())
.subscribeOn(Schedulers.newThread())
.subscribe(new Consumer<ResponseBody>() {
@Override
public void accept(ResponseBody responseBody) throws Throwable {
System.out.println(responseBody.string());
}
});
3垃僚、文件的上傳和下載
- 常用文件上傳格式對照
json : application/json
xml : application/xml
png : image/png
jpg : image/jpeg
gif : imge/gif
txt:text/plain
二進制數(shù)據(jù):multipart/form-data
- 文件上傳
創(chuàng)建對應的請求接口
public interface UploadService {
//文件上傳1個
@POST("post")
@Multipart
Call<ResponseBody> upload(@Part MultipartBody.Part file);
//文件上傳2個
@POST("post")
@Multipart
Call<ResponseBody> upload2(@Part MultipartBody.Part file,@Part MultipartBody.Part file2);
//上傳多個文件
@POST("post")
@Multipart
Call<ResponseBody> upload3(@PartMap Map<String, RequestBody> params);
}
對應的請求代碼:
public class UploadFileUnit {
//上傳單個文件
@Test
public void upload(){
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://www.httpbin.org").build();
UploadService uploadService = retrofit.create(UploadService.class);
File file = new File("C:\\Users\\Administrator\\Desktop\\1.txt");
MultipartBody.Part part = MultipartBody.Part
.createFormData("file","1.txt,",RequestBody.create(MediaType.parse("text/plain"),file));
Call<ResponseBody> call = uploadService.upload(part);
try {
Response<ResponseBody> response = call.execute();
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
//上傳兩個文件
@Test
public void upload2(){
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://www.httpbin.org").build();
UploadService uploadService = retrofit.create(UploadService.class);
//文件1,可以將text/plain替換城multipart/form-data
File file1 = new File("C:\\Users\\Administrator\\Desktop\\1.txt");
MultipartBody.Part part1 = MultipartBody.Part
.createFormData("file1","1.txt,",RequestBody.create(MediaType.parse("text/plain"),file1));
//文件2
File file2 = new File("C:\\Users\\Administrator\\Desktop\\2.txt");
MultipartBody.Part part2 = MultipartBody.Part
.createFormData("file2","2.txt,",RequestBody.create(MediaType.parse("text/plain"),file2));
Call<ResponseBody> call = uploadService.upload2(part1,part2);
try {
Response<ResponseBody> response = call.execute();
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
//上傳多個文件
@Test
public void uploadMore(){
Retrofit retrofit = new Retrofit.Builder().baseUrl("https://www.httpbin.org").build();
UploadService uploadService = retrofit.create(UploadService.class);
//發(fā)送大量二進制數(shù)據(jù)规辱,不限于文件
MediaType mediaType = MediaType.parse("multipart/form-data");
Map<String,RequestBody> params = new HashMap<>();
params.put("file[0]",MultipartBody.create(mediaType,new File("C:\\Users\\Administrator\\Desktop\\1.txt")));
params.put("file[1]",MultipartBody.create(mediaType,new File("C:\\Users\\Administrator\\Desktop\\2.txt")));
Call<ResponseBody> call = uploadService.upload3(params);
try {
Response<ResponseBody> response = call.execute();
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 文件下載
public interface DownLoadSercvice {
//下載文件
@Streaming
@GET
Call<ResponseBody> download(@Url String url);
}
對應請求:
@Test
public void downloadFile(){
Call<ResponseBody> call = downLoadSercvice.download("https://pacakge.cache.wpscdn.cn/wps/download/W.P.S.10577.12012.2019.exe");
try {
Response<ResponseBody> response = call.execute();
if (response.isSuccessful()){
//以文件流的形式
InputStream inputStream = response.body().byteStream();
FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\wps.exe");
int len;
byte[] buffer = new byte[4096];
while ((len =inputStream.read(buffer)) != -1){
fileOutputStream.write(buffer,0,len);
}
fileOutputStream.close();
inputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}