美文网首页
Retrofit的使用(二)

Retrofit的使用(二)

作者: BillyJean | 来源:发表于2022-04-04 14:26 被阅读0次

    这部分主要是实现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();
            }
        }
    

    相关文章

      网友评论

          本文标题:Retrofit的使用(二)

          本文链接:https://www.haomeiwen.com/subject/zujcsrtx.html