Retrofit的使用(二)

這部分主要是實現(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();
        }
    }
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末谆棺,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子罕袋,更是在濱河造成了極大的恐慌改淑,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浴讯,死亡現(xiàn)場離奇詭異朵夏,居然都是意外死亡,警方通過查閱死者的電腦和手機榆纽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門仰猖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人掠河,你說我怎么就攤上這事亮元∶图疲” “怎么了唠摹?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長奉瘤。 經(jīng)常有香客問我勾拉,道長,這世上最難降的妖魔是什么盗温? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任藕赞,我火速辦了婚禮,結果婚禮上卖局,老公的妹妹穿的比我還像新娘斧蜕。我一直安慰自己,他們只是感情好砚偶,可當我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布批销。 她就那樣靜靜地躺著,像睡著了一般染坯。 火紅的嫁衣襯著肌膚如雪均芽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天单鹿,我揣著相機與錄音掀宋,去河邊找鬼。 笑死,一個胖子當著我的面吹牛劲妙,可吹牛的內(nèi)容都是我干的湃鹊。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼是趴,長吁一口氣:“原來是場噩夢啊……” “哼涛舍!你這毒婦竟也來了?” 一聲冷哼從身側響起唆途,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤富雅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后肛搬,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體没佑,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年温赔,在試婚紗的時候發(fā)現(xiàn)自己被綠了蛤奢。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡陶贼,死狀恐怖啤贩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情拜秧,我是刑警寧澤痹屹,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站枉氮,受9級特大地震影響志衍,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜聊替,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一楼肪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧惹悄,春花似錦春叫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至爷速,卻和暖如春央星,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背惫东。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工莉给, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留毙石,地道東北人。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓颓遏,卻偏偏與公主長得像徐矩,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子叁幢,可洞房花燭夜當晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容