retrofit 學(xué)習(xí)筆記

ps: 我寫這篇這是很晚了痴昧,也是怪我自己啊,一直以來拖拖拉拉的就是改不了,retrofit 看著好幾次了米丘,看完有些日子就記不清了剑令,也沒記錄下來,忘了都沒地方找去拄查。所以今天好好理一理 retrofit 吁津,注解的使用還是很有必要記記的,誰也不敢打包票自己不忘是不堕扶,尤其是我腺毫,我對于這可是有深刻的印象啊,16年那會(huì)完全不寫博客挣柬,看了好多東西潮酒,看完就忘,結(jié)果發(fā)現(xiàn)16年的收獲慘不忍睹啊邪蛔。

另外說一點(diǎn)急黎,寫博客真是對知識(shí)點(diǎn)的理解和記憶是大大的加深啊,所以大家總是說好記性不如爛筆頭呀

retrofit 集成侧到,簡單使用


  1. 添加依賴
    // retrofit 依賴
    compile 'com.squareup.retrofit2:retrofit:2.4.0'
    compile 'com.squareup.retrofit2:converter-gson:2.4.0'
    compile 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
  1. 編寫遠(yuǎn)程接口
    retrofit 使用直接注解動(dòng)態(tài)生成遠(yuǎn)程請求 API 勃教,這讓我們專注于接口聲明,而不用去管理實(shí)現(xiàn)匠抗,既簡單又明了
public interface BlueService {
    @GET("book/search")
    Call<ResponseBody> getSearchBooks(@Query("q") String name,
                                      @Query("tag") String tag, @Query("start") int start,
                                      @Query("count") int count);
}
  1. 原生簡單請求
        String baseUrl = "https://api.douban.com/v2/";

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .build();

        BlueService blueService = retrofit.create(BlueService.class);
        blueService.getSearchBooks("小王子", "", 0, 3)
                .enqueue(new Callback<ResponseBody>() {
                    @Override
                    public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                        try {
                            String message = response.body().string();

                            Log.d("AAA", "onResponse: " + message);
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                    }

                    @Override
                    public void onFailure(Call<ResponseBody> call, Throwable t) {
                        Log.d("AAA", "onFailure: 聯(lián)網(wǎng)失敗");
                    }
                });

注意肮试础:

  • baseUrl 跟路徑必須以 “ / ” 結(jié)尾,現(xiàn)在強(qiáng)制要求了汞贸,不寫會(huì)報(bào)錯(cuò)
  • response.body().string() 可以獲取原始的 response 數(shù)據(jù)(字符串)绳军,我們使用的 .string() 而不是 .toString() , toString 出來的 class 名字。同時(shí)返回參數(shù)數(shù)據(jù)類型我們必須使用 ResponseBody 這個(gè)才行矢腻,這是 okhttp3 里面的门驾,這樣才能拿到原始響應(yīng)體
  • 這個(gè)寫法一般是獲取 json 轉(zhuǎn) bean 或是測試通不通用的,正常我們不這么用
  1. 添加 json 數(shù)據(jù)變換
        String baseUrl = "https://api.douban.com/v2/";

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        BlueService blueService = retrofit.create(BlueService.class);
        blueService.getSearchBooks("小王子", "", 0, 3)
                .enqueue(new Callback<BookResponse>() {
                    @Override
                    public void onResponse(Call<BookResponse> call, Response<BookResponse> response) {
                        try {
                            BookResponse bookResponse = response.body();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                    }

                    @Override
                    public void onFailure(Call<BookResponse> call, Throwable t) {
                        Log.d("AAA", "onFailure: 聯(lián)網(wǎng)失敗");
                    }
                });

這個(gè)我們在 retrofit.build 時(shí)添加了類型轉(zhuǎn)換器多柑,就可以讓 retrofit 自動(dòng)幫我們轉(zhuǎn)換 json 了奶是,然后遠(yuǎn)程接口,callback 我們都可以直接使用具體的數(shù)據(jù)類型了竣灌。我們還是 try 一下保險(xiǎn)

  1. 添加 rxjava 支持聂沙,變換請求結(jié)果為 observable
public interface BlueService {
    @GET("book/search")
    Observable<BookResponse> getSearchBooks(@Query("q") String name,
                                            @Query("tag") String tag, @Query("start") int start,
                                            @Query("count") int count);
}
        String baseUrl = "https://api.douban.com/v2/";

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();

        BlueService blueService = retrofit.create(BlueService.class);

        blueService.getSearchBooks("小王子", "", 0, 3)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<BookResponse>() {

                    Disposable disposable;

                    @Override
                    public void onSubscribe(Disposable d) {
                        disposable = d;
                    }

                    @Override
                    public void onNext(BookResponse bookResponse) {
                        Log.d("AAA", "onNext: " + bookResponse.getBooks().size());
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {
                        disposable.dispose();
                    }
                });
    }

要注意 rxjava2 的支持和1不同,rxjava2 的支持請安上面的依賴添加

中間插一段 http 協(xié)議基礎(chǔ)


我也是個(gè)搬運(yùn)工初嘹,http 協(xié)議我摘一點(diǎn)作用明顯的及汉,大家看看,然后覺得不怎么懂就去專門看下削樊,我在下面會(huì)附上地址的

HTTP 的請求報(bào)文分為三個(gè)部分 請求行豁生、請求頭和請求體兔毒,格式如圖:


1724103-c43900117e983241.png
  1. 請求行

請求行(Request Line)分為三個(gè)部分:請求方法漫贞、請求地址和協(xié)議及版本甸箱,HTTP/1.1 定義的請求方法有8種:

  • GET、POST迅脐、PUT芍殖、DELETE、PATCH谴蔑、HEAD豌骏、OPTIONS、TRACE隐锭,最常的兩種GET和POST
  • RestFul 規(guī)范的接口的話會(huì)用到 GET窃躲、POST、DELETE钦睡、PUT蒂窒,分別對應(yīng)數(shù)據(jù)庫的增刪改查操作:
    • PUT -> 增
    • DELETE -> 刪
    • POST -> 改
    • GET -> 查

在了解請求地址之前,先了解一下URL的構(gòu)成:


1724103-95c263da5671d6fa.png

所以我們在 retrofit 的 baseUrl 添加跟地址的行為就是添加 http 協(xié)議和主機(jī)地址

Retrofit retrofit = new Retrofit.Builder()
    .baseUrl(baseUrl)

剩下的 http 基礎(chǔ)內(nèi)容還有很多荞怒,我就不復(fù)制了洒琢,大家看這里:你應(yīng)該知道的HTTP基礎(chǔ)知識(shí),一定要看哦褐桌,要不后面你會(huì)暈衰抑,有地方搞不明白的

  1. 請求頭
    其中有一點(diǎn)我們一定要弄清楚的是 http 請求體類型,也就是我們會(huì)看到的 Content-Type
  • Content-Type:application/json
    表示這是提交的 json
  • Content-Type:application/x-www-form-urlencoded
    表單提交
  • Content-Type:multipart/form-data; boundary={boundary}
    文件提交荧嵌,也叫模擬表單

重頭戲來啦呛踊,注解詳解


整篇文章的重點(diǎn)就在這啦,前面的都是浮云啦撮,初次使用的同學(xué)可能覺得有些繁瑣恋技,有些不好理解,但是對于有點(diǎn)水平的同學(xué)們來說就不叫事了不是逻族,所x以注解這個(gè)才是我們需要重點(diǎn)學(xué)習(xí)的蜻底,看了上面的 http 協(xié)議的部分知識(shí)點(diǎn),我們再去研究下 retrofit 的注解就不是那么撓頭了

1. 請求類型

請求類型是請求頭中的一個(gè)內(nèi)容聘鳞,寫在 header 里薄辅,字段是:Content-Type,是描述我們給服務(wù)器發(fā)送的數(shù)據(jù)采用什么格式發(fā)送抠璃,下面放個(gè)例子:

interface APIStore {
   @Headers({"Content-Type: application/json","Accept: application/json"})
   @POST ("vdyweb/ws/rest/Login")
   Call<ResponseBody>getMessage(@Body RequestBody info);   
}

大家看到在請求頭中添加了 Content-Type 字段的數(shù)據(jù)站楚,這里總結(jié)下有幾種請求方式啊,這點(diǎn)很重要的搏嗡,寫不對你的遠(yuǎn)程通訊就會(huì)不同窿春,或是服務(wù)器拿不到數(shù)據(jù)哦拉一。retrofit 已經(jīng)為我們封裝好了常用的請求方式,這里結(jié)合的說一下:

  • 什么都不寫
    什么都不寫表示傳遞參數(shù)沒有規(guī)范旧乞,發(fā)送過去的是二進(jìn)制流蔚润,傳值你得用 @Body 注解,服務(wù)器接受到的是二進(jìn)制流尺栖,然后可以轉(zhuǎn)成字符串按 json 解析數(shù)據(jù)嫡纠,不過一般我么不推薦這么寫。
  • json 提交
    json 的話我司現(xiàn)在就是用這種方法延赌,適合做 post 萬能請求接口除盏,不過在 RestFul 規(guī)范的今天, 不在推薦這么寫了挫以,我們也得讓后臺(tái)兄弟舒服不是者蠕。所以我們在 retrofit 找不到這個(gè)注解,就是因?yàn)椴煌扑]這種寫法了掐松, 下面是自己寫的方式踱侣,這里只是接口聲明,詳細(xì)在后面
interface APIStore {
   @Headers({"Content-Type: application/json","Accept: application/json"})
   @POST ("vdyweb/ws/rest/Login")
   Call<ResponseBody>getMessage(@Body  Book book);  
}

@Body 的數(shù)據(jù)對象甩栈,Retrofit2 會(huì)自動(dòng)轉(zhuǎn)成 Gson 字符串發(fā)送

  • get 方式
    get 方式很特殊泻仙,大家都知道 get 請求方式很特殊,把一切都拼接在 url 地址中量没,所以沒那么復(fù)雜玉转, Content-Type 不用設(shè)置
  • 表單提交
    表單提交,數(shù)據(jù)都以 key—value 的形式存在請求體中殴蹄,服務(wù)器獲取參數(shù)也是用 key—value 的形式去拿數(shù)據(jù)究抓,作為最常使用的提交方式,retrofit 已經(jīng)給我們封裝好了袭灯,專門有一個(gè)字段
    @FormUrlEncoded
    Observable<BookResponse> getSearchBooks(@Query("q") String name);

自己寫的話就是

    @Headers("Content-Type:application/x-www-form-urlencoded")
    Observable<BookResponse> getBooks();
  • 模擬表單
    在表單提交的基礎(chǔ)上可以添加文件數(shù)據(jù)刺下,retrofit 也給我們封裝好了
    @Multipart
    Observable<BookResponse> getBooks();

自己寫的話就是

    @Headers("Content-Type:multipart/form-data; boundary={boundary}")
    Observable<BookResponse> getBooks();

boundary 部分可寫可不些,我看有人不寫 boundary 也沒事稽荧,boundary=xxxxxxx橘茉,xxxxxx規(guī)定了請求體中的內(nèi)容分隔符

  • 文檔相關(guān)資料


    retrofit3.png

2. 請求方法

請求方法上面 http 基礎(chǔ)應(yīng)說過了,這個(gè)不難理解姨丈,需要注意的是 restFul 規(guī)范下的部分:
* PUT -> 增
* DELETE -> 刪
* POST -> 改
* GET -> 查
這里要提一下 http 這個(gè)請求方法畅卓,HTTP注解則可以代替任意一個(gè)青谷去方法,有3個(gè)屬性:method蟋恬,path翁潘,hasBody,下面是例子:

public interface BlogService {
    /**
     * method 表示請的方法歼争,不區(qū)分大小寫
     * path表示路徑
     * hasBody表示是否有請求體
     */
    @HTTP(method = "get", path = "blog/{id}", hasBody = false)
    Call<ResponseBody> getFirstBlog(@Path("id") int id);
} 

3. 數(shù)據(jù)接收類型

在 http 協(xié)議中可以指定接受服務(wù)器返回?cái)?shù)據(jù)的類型拜马,這個(gè)一般我們不用自己去設(shè)置渗勘,retrofit 默認(rèn)就是 json 格式的,但是自己也可以設(shè)俩莽,使用的是上面可以看到的 Accept 這個(gè)字段

@Headers({"Content-Type: application/json","Accept: application/json"})

寫在 head 請求頭了旺坠,看到這大家可以發(fā)現(xiàn),這些設(shè)置除了 get/post 之外豹绪,所有的請求設(shè)置都是寫在請求頭里的价淌,請求頭就是干這事的申眼,類似于我們常用的 config 瞒津,包裹配置參數(shù)和一些通用參數(shù)。
retrofit 還提供了 @Streaming 這個(gè)注解括尸,我們接收的數(shù)據(jù)不再是 json 的了巷蚪,而是一個(gè)二進(jìn)制輸入流。

    @Streaming

4. 傳參相關(guān)參數(shù)

retrofit4.png

retrofit 用來在不同請求方法中傳遞參數(shù)的注解都在上面了濒翻,單說沒意思屁柏,結(jié)合 get / post 和請求不同的數(shù)據(jù)來說最簡單明了,容易懂有送。

5. get 傳參詳解

    @GET("xxxUrl")
    Observable<User> getUserInfo(
            @Part("xxxUrl") String userUrl,
            @Query("userid") int id,
            @QueryMap Map<String, String> options,
            @Query("list") List<String> options2);

可以看到 get 可以接受4種傳參注解:

  • @Part -1
    用來替換具體的 utl 路徑的淌喻,一般我們都是直接就寫 url 地址了,這里通過 @Part 提供一種動(dòng)態(tài)傳入 url 地址方式雀摘,@Part 注解是所有請求方法通用的裸删。
  • @Part -2
    上面的 @Part 寫法是整體替換具體的 URL 請求,其實(shí)要是后臺(tái)同學(xué)的 restFul API 寫的規(guī)范的話阵赠,我們請求涯塔,操作數(shù)據(jù)的 URL 也是可以做到動(dòng)態(tài)的,不是費(fèi)的一個(gè)接口寫一個(gè)固定的地址給我們清蚀。這時(shí) @Part 可以用來實(shí)現(xiàn)動(dòng)態(tài)替換 URL 中參數(shù)的事匕荸,使用 {“xxx”} 來標(biāo)記 URL 中可變的部分,下面就是一個(gè)例子:
    @GET("book/{id}")
    Observable<User> getBook(@Part("id") String id);
  • @Query
    傳單個(gè)參數(shù)枷邪,Query("userid") 里面的字符串是 key榛搔,后面指定 value 的類型
  • @QueryMap
    可以接受多個(gè)參數(shù),所有參數(shù)直接寫在 map 里
  • Query("list")
    get 方式支持直接傳入一個(gè)集合东揣,可以看到其實(shí)和我們單個(gè)傳參一樣践惑,只不過區(qū)別是接收的數(shù)據(jù)是單個(gè)對象,還是一個(gè)集合對象

6. post 傳參詳解

    @POST("xxxUrl")
    Observable<User> getUserInfo(
            @Field("userid") int id,
            @FieldMap Map<String, String> options,
            @Field("list") List<String> options2);

post 傳參其實(shí)和 get 差不多救斑,卻別不多童本,一個(gè)是 query ,一個(gè)是 field

  • @Field
    傳單個(gè)參數(shù)脸候,和 @Query 一樣
  • @FieldMap
    傳多個(gè)數(shù)據(jù)
  • @Field("list")
    同樣支持直接傳遞集合數(shù)據(jù)類型
  • @POST
    @POST 除了get 都能用穷娱,用來傳遞一個(gè)數(shù)據(jù)對象绑蔫,服務(wù)器按 stream 流的方式接收數(shù)據(jù)
    @POST("name")
    Observable<User> getName(@Body Book book);

7. 上傳文件

上傳文件一直是個(gè)有問題的地方,不管是 Xutils泵额,okhttp配深,retrofit 都有不是很明確的地方,這里就能看出網(wǎng)絡(luò)基礎(chǔ)是多么重要嫁盲,有時(shí)候你寫完之后篓叶,服務(wù)器接收不到參數(shù),或是問你發(fā)的數(shù)據(jù)用的什么類型羞秤,我怎么接受缸托,你都回答不上來,這個(gè)很尷尬不是瘾蛋,我是遇到過俐镐,還好后臺(tái)的兄弟沒打我臉,哈哈哈哈.......

不看我寫的哺哼,看看這些文章也是可以的:

有一點(diǎn)我們要說,表單提交的時(shí)候參數(shù)的編碼問題 enctype屬性取董。enctype:規(guī)定了form表單在發(fā)送到服務(wù)器時(shí)候編碼方式棍苹,他有如下的幾個(gè)值:

  • application/x-www-form-urlencoded
    默認(rèn)值,不寫就是這個(gè)茵汰,retrofit 的表單默認(rèn)也是這個(gè)枢里,不能用來傳文件,也就是二進(jìn)制數(shù)據(jù)
  • multipart/form-data
    所有的數(shù)據(jù)以二進(jìn)制流發(fā)送
  • application/otcet-stream
    很奇怪经窖,我查了查是八進(jìn)制.........這個(gè)恕我真的不知道為啥有二進(jìn)制不用坡垫,去用八進(jìn)制
  • text/plain
    純文本格式

在帶有 file 的表單提交中:

  • file 只能用流的形式上傳
    • 可以用:multipart/form-data / application/otcet-stream 這2種流上傳,差別估計(jì)是后臺(tái)接受數(shù)據(jù)的 API 不同画侣。
  • 文本參數(shù)可以用流的方式上傳冰悠,也可以用文本格式上傳
    • 可以使用 multipart/form-data 這樣后臺(tái)用流接數(shù)據(jù),getParame 拿不到數(shù)據(jù)的配乱。
    • 最好用 text/plain 文本格式傳溉卓,這樣后臺(tái)獲取數(shù)據(jù)和原來的方式相同。

好了看過這些搬泥,我們心里總算是對這些彎彎繞的東西有些初步了解了桑寨,再去和后臺(tái)溝通也大概知道怎么說了,查資料也知道去找什么東東了

    @Multipart
    @POST("upload")
    Call<ResponseBody> uploadMultipleFiles(
            @Part("description") RequestBody description,
            @PartMap Map<String, RequestBody> options
            @Part MultipartBody.Part file1,
            @Part MultipartBody.Part file2);

這是一個(gè)帶其他參數(shù)的文件上傳 API 忿檩,大家注意看注解如何使用尉尾,這個(gè)是固定的,大家背下來就行燥透。期中 @Part("description") 里面的字符串是普通文本參數(shù)的 key

我們來看看重點(diǎn)的 java 代碼:

  • 創(chuàng)建文本參數(shù)
    注意這里我用的是 text/plain 發(fā)送文本參數(shù)沙咏,用 multipart/form-data 二進(jìn)制的方式也可以的
RequestBody requestBody = RequestBody.create(MediaType.parse("text/plain"), "文本參數(shù)");
  • 創(chuàng)建 file 參數(shù)
        File imageFile = new File("一張圖片");
        RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), imageFile);
        MultipartBody.Part data = MultipartBody.Part.createFormData("file", imageFile.getName(), requestBody);
  • 文件數(shù)據(jù)傳入 map 集合中的寫法
    可能我們的接口是這樣的
    @POST("NewsServlet")
    @Multipart
    Call<ResponseBody> testFileUpload3(@PartMap Map<String, RequestBody> map);

所有參數(shù)都放在這個(gè)集合中辨图,集合參數(shù)的放置如下,注意 file 類型的參數(shù)的 key 要包含 file 的name 進(jìn)去肢藐,需要自己拼接字符串的

        NewsService newsService = createRetrofit().create(NewsService.class);
         Map<String, RequestBody> fileUpload3Args = new HashMap<>();

        MediaType textType = MediaType.parse("text/plain");
        RequestBody name = RequestBody.create(textType, "txy");
        RequestBody age = RequestBody.create(textType, "18");

        fileUpload3Args.put("name", name);
        fileUpload3Args.put("age", age);

        //構(gòu)建要上傳的文件
        File file = new File(Environment.getExternalStorageDirectory(), "paoche1.jpg");
        RequestBody requestFile =
                RequestBody.create(MediaType.parse("application/otcet-stream"), file);

        fileUpload3Args.put("fileUploader\"; filename=\"paoche3.jpg",requestFile);

        Call<ResponseBody> answers = newsService.testFileUpload3(fileUpload3Args)

上傳文件基本就是這些了故河,這塊容易忘,容易混吆豹,記下來非常有必要的鱼的。

8. 上傳圖片

上傳圖片看這篇也行,總結(jié)的也很好痘煤,比我全面一點(diǎn):

圖片也是文件凑阶,但是為啥要單獨(dú)拿出來說呢,因?yàn)閳D片有自己單獨(dú)的數(shù)據(jù)格式 : image/png

RequestBody photoRequestBody = RequestBody.create(MediaType.parse("image/png"), imageFile);
MultipartBody.Part photo = MultipartBody.Part.createFormData("上傳的key", "文件名.png", photoRequestBody);

9. 添加請求頭參數(shù)

請求頭參數(shù)我們可以在網(wǎng)絡(luò)請求的 API 接口里寫速勇,也可以給 okhttp 添加一個(gè)攔截器進(jìn)來晌砾,在請求構(gòu)建完成坎拐,發(fā)送前的那一刻攔截烦磁,然后添加請求頭數(shù)據(jù),這樣適合添加動(dòng)態(tài)可變參數(shù)

  • @Headers 添加靜態(tài)請求頭參數(shù)
public interface BlueService {
    @Headers("Cache-Control: max-age=640000")
    @Headers({
        "Accept: application/vnd.yourapi.v1.full+json",
        "User-Agent: Your-App-Name"
    })
    @GET("book/search")
    Call<BookSearchResponse> getSearchBooks(@Query("q") String name, 
            @Query("tag") String tag, @Query("start") int start, 
            @Query("count") int count);
}

注意添加一條和多條的區(qū)別

  • @Header 添加動(dòng)態(tài)請求頭參數(shù)
public interface BlueService {
    @GET("book/search")
    Call<BookSearchResponse> getSearchBooks(
    @Header("Content-Range") String contentRange, 
    @Query("q") String name, @Query("tag") String tag, 
    @Query("start") int start, @Query("count") int count);
}
  • 添加攔截器動(dòng)態(tài)添加請求頭參數(shù)
public class HeadInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request original = chain.request();
        Request request = original.newBuilder()
            .header("User-Agent", "Your-App-Name")
            .header("Accept", "application/vnd.yourapi.v1.full+json")
            .method(original.method(), original.body())
            .build();
        return chain.proceed(request);
    }
}
        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(new HeadInterceptor ())
                .build();

        Retrofit retrofit = new Retrofit.Builder()
                .client(client)
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();

添加 header 參數(shù) Request 提供了兩個(gè)方法:

  • header(key, value)
    如果有重名的將會(huì)覆蓋
  • ddHeader(key, value)
    允許相同 key 值的 header 存在

10. 為某個(gè)請求設(shè)置完整的URL

有個(gè)別的請求的 URL 不用用的我們基礎(chǔ)的 baseurl 的哼勇,怎么辦都伪,我們可以使用 @Url 注解來忽略 baseurl 的

@GET
public Call<ResponseBody> profilePicture(@Url String url);

Retrofit retrofit = Retrofit.Builder()  
    .baseUrl("https://your.api.url/");
    .build();

BlueService service = retrofit.create(BlueService.class);  
service.profilePicture("https://s3.amazon.com/profile-picture/path");

json 上傳的再次說明


json 上傳數(shù)據(jù)不推薦,但是有時(shí)候我們真的需要积担,這里多記錄一下找到的東西陨晶。

json 除了我們直接 @Body Book book 直接寫具體的數(shù)據(jù)類型的做法,我們也可以使用 RequestBody 來寫

public interface PostRoute {  
   @Headers({"Content-Type: application/json","Accept: application/json"})
    @POST("api/FlyRoute/Add")  
   Call<FlyRouteBean> postFlyRoute(@Body RequestBody route)RequestBody  
}  
// 先 json 一個(gè)字符串?dāng)?shù)據(jù)出來
Book book= new Book ();  
Gson gson=new Gson();  
String route = gson.toJson(book);

// 我們生成一個(gè) RequestBody 請求對象出來
PostRoute postRoute=retrofit.create(PostRoute.class);  
RequestBody body=RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"),route);  
Call<Book> call=postRoute.postFlyRoute(body);  

添加日志管理


這個(gè)是 okhttp 的部分帝璧,但是呢我們不打算專門寫一個(gè) okhttp 的入了先誉,在 retrofit 中我們已經(jīng)充分使用了 okhttp 了,索性就一起寫了

retrifit 又開源的日志攔截器的烁,要不我們就自己寫攔截器打印日志褐耳,不過肯定大的不如直接誒個(gè)開源的全啊渴庆。

添加依賴

compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'

使用

        // 創(chuàng)建日志攔截器對象出來
        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
        //包含header、body數(shù)據(jù)
        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

        // 添加日志攔截器到 okhttp 對象中
        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(loggingInterceptor)
                .build();

        // 把 okhttp 對象添加到 retrofit 對象中
        Retrofit retrofit = new Retrofit.Builder()
                .client(client)
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();

打印樣式圖:


436713-a7e0267212e9f809.png

注意里面 --> 刃滓、<-- 箭頭的方向:

  • --> 表示我們請求的內(nèi)容,包括請求頭參數(shù)耸弄,請求信息等,這里我們是最簡單的 get 請求所以表現(xiàn)不出來
  • <-- 是我們接受到的內(nèi)容计呈,包括接受數(shù)據(jù)形式
  • interceptor 有幾個(gè)級別僚饭,我們用 body 就行胧砰,body 會(huì)代印包括頭在內(nèi)的所有信息

facebook 網(wǎng)絡(luò)調(diào)試器 Stetho


我還看到有一位朋友提到 facebook 開源了 Stetho 網(wǎng)絡(luò)監(jiān)測工具,試了試我沒成功尉间,有興趣的朋友請看:使用OkHttp高效開發(fā)調(diào)試

其他內(nèi)容


對于 https 證書有兩種策略:

參考資料


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末童芹,一起剝皮案震驚了整個(gè)濱河市涮瞻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌假褪,老刑警劉巖署咽,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異祟峦,居然都是意外死亡该面,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進(jìn)店門赡矢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來慕匠,“玉大人饱须,你說我怎么就攤上這事√ㄒ辏” “怎么了蓉媳?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長锅铅。 經(jīng)常有香客問我酪呻,道長,這世上最難降的妖魔是什么盐须? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任玩荠,我火速辦了婚禮,結(jié)果婚禮上贼邓,老公的妹妹穿的比我還像新娘阶冈。我一直安慰自己,他們只是感情好立帖,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布眼溶。 她就那樣靜靜地躺著,像睡著了一般晓勇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上灌旧,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天绑咱,我揣著相機(jī)與錄音,去河邊找鬼枢泰。 笑死描融,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的衡蚂。 我是一名探鬼主播窿克,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼毛甲!你這毒婦竟也來了年叮?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤玻募,失蹤者是張志新(化名)和其女友劉穎只损,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡跃惫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年叮叹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片爆存。...
    茶點(diǎn)故事閱讀 39,754評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情债朵,我是刑警寧澤,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布宪塔,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏霉赡。R本人自食惡果不足惜迫肖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一故爵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧隅津,春花似錦诬垂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至充蓝,卻和暖如春隧枫,著一層夾襖步出監(jiān)牢的瞬間谓苟,已是汗流浹背官脓。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留涝焙,地道東北人卑笨。 一個(gè)月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像仑撞,于是被迫代替她去往敵國和親赤兴。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評論 2 354

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