Retrofit的使用(二)

這部分主要是實(shí)現(xiàn)Retrofit的轉(zhuǎn)換器使用,以及實(shí)現(xiàn)cookies緩存+嵌套請(qǐng)求,文件的上傳和下載

  • 相關(guān)依賴
    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、使用轉(zhuǎn)換器

和前面一樣,也是要?jiǎng)?chuàng)建請(qǐng)求的接口:

public interface WanAndroidService {
   //不使用轉(zhuǎn)換器,直接使用Gson來轉(zhuǎn)換
    @POST("user/login")
    @FormUrlEncoded
    Call<ResponseBody> loginWanAndroid(@Field("username") String username,@Field("password") String password);

    //使用轉(zhuǎn)換器,ResponseBody只能得到字符串,用轉(zhuǎn)換器轉(zhuǎn)換成Bean對(duì)象
    @POST("user/login")
    @FormUrlEncoded
    Call<WanAndroidBean> loginWanAndroid2(@Field("username") String username,@Field("password") String password);
}

接著在Java環(huán)境中創(chuàng)建對(duì)應(yīng)的測試單元(對(duì)應(yīng)的WanAndroidBean .java可以用PostMan配合GsonFormat插件自動(dòng)生成):

//retrofit轉(zhuǎn)換器測試
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手動(dòng)轉(zhuǎn)換
            //將Json字符串轉(zhuǎn)換成對(duì)應(yīng)的對(duì)象
            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/")
                //第二種:添加轉(zhuǎn)換器,讓Retrofit自動(dòng)轉(zhuǎn)換,使用GsonConvertFactory將json數(shù)據(jù)轉(zhuǎn)換成對(duì)象
                .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、使用嵌套請(qǐng)求+cookies緩存

嵌套請(qǐng)求是指在請(qǐng)求有順序的情況下,例如必須要先登錄再獲取文章列表,有先后順序,

  • 封裝請(qǐng)求的接口
public interface WanAndroidService {
   //使用適配器,與Rxjava聯(lián)合使用
    @POST("user/login")
    @FormUrlEncoded
    Flowable<WanAndroidBean> login2(@Field("username")String username,@Field("password")String password);
  
    //請(qǐng)求文章列表
    @GET("lg/collect/list/{pageNum}/json")
    Flowable<ResponseBody> getArticle(@Path("pageNum")int pageNum);
}
  • 實(shí)際請(qǐng)求,這里加入了Rxjava的轉(zhuǎn)換器
  //使用適配器,實(shí)現(xiàn)嵌套請(qǐng)求
    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())
                //第二種:添加轉(zhuǎn)換器,讓Retrofit自動(dòng)轉(zhuǎn)換,使用GsonConvertFactory將json數(shù)據(jù)轉(zhuǎn)換成對(duì)象
                .addConverterFactory(GsonConverterFactory.create())
                //添加適配器,讓它不再是單一的Call對(duì)象,改為Rxjava的Flowable對(duì)象
                .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
                .build();
        WanAndroidService wanAndroidService = retrofit.create(WanAndroidService.class);

        //使用的是Rxjava的線程切換調(diào)用
       //1.先登錄
        wanAndroidService.login2("用戶名", "密碼")
                //生成一個(gè)新的publish
                .flatMap(new Function<WanAndroidBean, Publisher<ResponseBody>>() {
                    @Override
                    public Publisher<ResponseBody> apply(WanAndroidBean wanAndroidBean) throws Throwable {
                        //2.嵌套請(qǐng)求,請(qǐng)求文章列表
                        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、文件的上傳和下載

  • 常用文件上傳格式對(duì)照
json : application/json
xml : application/xml
png : image/png
jpg : image/jpeg
gif : imge/gif
txt:text/plain
二進(jìn)制數(shù)據(jù):multipart/form-data

  • 文件上傳
    創(chuàng)建對(duì)應(yīng)的請(qǐng)求接口
public interface UploadService {
    //文件上傳1個(gè)
    @POST("post")
    @Multipart
    Call<ResponseBody> upload(@Part MultipartBody.Part file);

    //文件上傳2個(gè)
    @POST("post")
    @Multipart
    Call<ResponseBody> upload2(@Part MultipartBody.Part file,@Part MultipartBody.Part file2);

    //上傳多個(gè)文件
    @POST("post")
    @Multipart
    Call<ResponseBody> upload3(@PartMap Map<String, RequestBody> params);
}

對(duì)應(yīng)的請(qǐng)求代碼:

public class UploadFileUnit {

    //上傳單個(gè)文件
    @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();
        }
    }

    //上傳兩個(gè)文件
    @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();
        }
    }

    //上傳多個(gè)文件
    @Test
    public void uploadMore(){
        Retrofit retrofit = new Retrofit.Builder().baseUrl("https://www.httpbin.org").build();
        UploadService uploadService = retrofit.create(UploadService.class);

        //發(fā)送大量二進(jìn)制數(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);
}

對(duì)應(yīng)請(qǐng)求:

 @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();
        }
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容