这部分主要是实现Retrofit的转换器使用,以及实现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、使用转换器
和前面一样,也是要创建请求的接口:
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环境中创建对应的测试单元(对应的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数据转换成对象
.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联合使用
@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的转换器
//使用适配器,实现嵌套请求
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数据转换成对象
.addConverterFactory(GsonConverterFactory.create())
//添加适配器,让它不再是单一的Call对象,改为Rxjava的Flowable对象
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.build();
WanAndroidService wanAndroidService = retrofit.create(WanAndroidService.class);
//使用的是Rxjava的线程切换调用
//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
二进制数据:multipart/form-data
- 文件上传
创建对应的请求接口
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);
//发送大量二进制数据,不限于文件
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();
}
}