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

參考:

使用流程

  1. 添加依賴
    implementation 'com.squareup.okhttp3:okhttp:3.11.0'
    implementation 'com.squareup.retrofit2:retrofit:2.4.0'
  1. 添加網(wǎng)絡(luò)權(quán)限
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
  1. 創(chuàng)建接收服務(wù)器返回數(shù)據(jù)的類
public class Persion {
    ...
    // 根據(jù)返回數(shù)據(jù)的格式和數(shù)據(jù)解析方式(Json扫茅、XML等)定義
    // 下面會在實例進(jìn)行說明
}
  1. 創(chuàng)建用于描述網(wǎng)絡(luò)請求的接口
public interface GetRequest_Interface {

    @GET("persion")
    Call<Persion>  getPersion();
    // @GET注解的作用:采用Get方法發(fā)送網(wǎng)絡(luò)請求

    // getCall() = 接收網(wǎng)絡(luò)請求數(shù)據(jù)的方法
    // 其中返回類型為Call<*>没陡,*是接收數(shù)據(jù)的類(即上面定義的Persion類)
    // 如果想直接獲得Responsebody中的內(nèi)容,可以定義網(wǎng)絡(luò)請求返回值為Call<ResponseBody>
  1. 創(chuàng)建Retrofit對象
Retrofit retrofit=new Retrofit.Builder()
                .baseUrl("address/")   //設(shè)置網(wǎng)絡(luò)請求的URL地址
                .addConverterFactory(GsonConverterFactory.create())   //設(shè)置數(shù)據(jù)解析器
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) // 支持RxJava平臺
                .build();

完整的URL地址=baseUrl+@GET()中的參數(shù)
上面的請求地址:address/persion
有一點注意如果是本機(jī)測試不要用localhost和127.0.0.1
還可以用動態(tài)傳遞請求參數(shù)
ConverterFactory和CallAdapterFactory請往后看

  1. 創(chuàng)建網(wǎng)絡(luò)請求接口實例 并 配置網(wǎng)絡(luò)請求參數(shù)
GetPersion_Interface getPersion_interface=retrofit.create(GetPersion_Interface.class);

        Call<Persion> call=getPersion_interface.getPersion();
  1. 發(fā)送網(wǎng)絡(luò)請求(異步 / 同步)
call.enqueue(new Callback<Persion>() {
            @Override
            public void onResponse(Call<Persion> call, Response<Persion> response) {
                textView.setText("Id:"+response.body().getId()+" "+"Name:"+response.body().getName()+" "+"Age:"+response.body().getAge());
            }

            @Override
            public void onFailure(Call<Persion> call, Throwable t) {
                textView.setText("請求失敗");
            }
        });

這里采用異步操作
在這里有一個注意點蔫敲,如果要返回ResponseBody的話,response.body().string()而不是toString

注解類型

網(wǎng)絡(luò)請求方法注解

注解 解釋
@GET 請求指定的頁面信息,并返回實體主體
@POST 向指定資源提交數(shù)據(jù)進(jìn)行處理請求(例如提交表單或者上傳文件)队秩。數(shù)據(jù)被包含在請求體中。POST請求可能會導(dǎo)致新的資源的建立和/或已有資源的修改
@PUT 從客戶端向服務(wù)器傳送的數(shù)據(jù)取代指定的文檔的內(nèi)容
@HEAD 類似于get請求昼浦,只不過返回的響應(yīng)中沒有具體的內(nèi)容馍资,用于獲取報頭
@DELETE 請求服務(wù)器刪除指定的頁面
@CONNECT HTTP/1.1協(xié)議中預(yù)留給能夠?qū)⑦B接改為管道方式的代理服務(wù)器。
@OPTIONS 允許客戶端查看服務(wù)器的性能关噪。
@HTTP 用于替換以上7個注解的作用以及更多功能拓展
  • @HTTP描述
    如下:
public interface GetRequest_Interface {
    /**
     * method:網(wǎng)絡(luò)請求的方法(區(qū)分大小寫)
     * path:網(wǎng)絡(luò)請求地址路徑
     * hasBody:是否有請求體
     */
    @HTTP(method = "GET", path = "blog/{id}", hasBody = false)
    Call<ResponseBody> getCall(@Path("id") int id);
    // {id} 表示是一個變量
    // method 的值 retrofit 不會做處理鸟蟹,所以要自行保證準(zhǔn)確
}

標(biāo)記類注解

注解 解釋
@FormUrlEncoded 表示請求體是一個Form表單
@Multipart 表示請求體是一個支持文件上傳的Form表單
@Streaming 表示數(shù)據(jù)以流的形式返回,適用于返回數(shù)據(jù)大的情況(如果沒有該注解使兔,默認(rèn)把數(shù)據(jù)全部載入內(nèi)存建钥,之后獲取數(shù)據(jù)也是從內(nèi)存中提取)
  • @FormUrlEncoded

表示發(fā)送form-encoded的數(shù)據(jù)
每個鍵值對需要用@Filed來注解鍵名虐沥,隨后的對象需要提供值锦针。

  • @Multipart

作用:表示發(fā)送form-encoded的數(shù)據(jù)(適用于 有文件 上傳的場景)
每個鍵值對需要用@Part來注解鍵名,隨后的對象需要提供值置蜀。
具體使用如下:
GetRequest_Interface

public interface GetRequest_Interface {
        /**
         *表明是一個表單格式的請求(Content-Type:application/x-www-form-urlencoded)
         * <code>Field("username")</code> 表示將后面的 <code>String name</code> 中name的取值作為 username 的值
         */
        @POST("/form")
        @FormUrlEncoded
        Call<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age);

        /**
         * {@link Part} 后面支持三種類型奈搜,{@link RequestBody}、{@link okhttp3.MultipartBody.Part} 盯荤、任意類型
         * 除 {@link okhttp3.MultipartBody.Part} 以外馋吗,其它類型都必須帶上表單字段({@link okhttp3.MultipartBody.Part} 中已經(jīng)包含了表單字段的信息),
         */
        @POST("/form")
        @Multipart
        Call<ResponseBody> testFileUpload1(@Part("name") RequestBody name, @Part("age") RequestBody age, @Part MultipartBody.Part file);

}

// 具體使用
       GetRequest_Interface service = retrofit.create(GetRequest_Interface.class);
        // @FormUrlEncoded 
        Call<ResponseBody> call1 = service.testFormUrlEncoded1("Carson", 24);

        //  @Multipart
        RequestBody name = RequestBody.create(textType, "Carson");
        RequestBody age = RequestBody.create(textType, "24");

        MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", "test.txt", file);
        Call<ResponseBody> call3 = service.testFileUpload1(name, age, filePart);

網(wǎng)絡(luò)請求參數(shù)注解

注解 解釋
@Headers 添加請求頭(注釋在方法上)
@Header 添加不固定值的請求頭(用在參數(shù)中)
@Body 用于非表單請求體( 不能用在get 請求方法)
@Field 向Post表單傳入鍵值對
@FieldMap 向Post表單傳入鍵值對(多個)
@Part 用于表單字段秋秤,適用于有文件上傳的情況
@PartMap 用于表單字段宏粤,適用于有文件上傳的情況
@Query 用于表單字段用在get方法上
@QueryMap 用于表單字段用在get方法上
@Path URL缺省值
@URL URL設(shè)置

@Field @Body一般用于Post方法,參數(shù)在請求體里
@Query 用在get方法灼卢,參數(shù)在請求頭

  • @Header & @Headers

添加請求頭 &添加不固定的請求頭

// @Header
@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)

// @Headers
@Headers("Authorization: authorization")
@GET("user")
Call<User> getUser()

// 以上的效果是一致的绍哎。
// 區(qū)別在于使用場景和使用方式
// 1. 使用場景:@Header用于添加不固定的請求頭,@Headers用于添加固定的請求頭
// 2. 使用方式:@Header作用于方法的參數(shù)鞋真;@Headers作用于方法
  • @Body

以 Post方式 傳遞 自定義數(shù)據(jù)類型 給服務(wù)器,類的實例啥的
特別注意:如果提交的是一個Map崇堰,那么作用相當(dāng)于 @Field
不過Map要經(jīng)過 FormBody.Builder 類處理成為符合 Okhttp 格式的表單,如:

FormBody.Builder builder = new FormBody.Builder();
builder.add("key","value");
  • @Field & @FieldMap

發(fā)送 Post請求 時提交請求的表單字段
具體使用:與 @FormUrlEncoded 注解配合使用

public interface GetRequest_Interface {
        /**
         *表明是一個表單格式的請求(Content-Type:application/x-www-form-urlencoded)
         * <code>Field("username")</code> 表示將后面的 <code>String name</code> 中name的取值作為 username 的值
         */
        @POST("/form")
        @FormUrlEncoded
        Call<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age);

/**
         * Map的key作為表單的鍵
         */
        @POST("/form")
        @FormUrlEncoded
        Call<ResponseBody> testFormUrlEncoded2(@FieldMap Map<String, Object> map);

}

// 具體使用
         // @Field
        Call<ResponseBody> call1 = service.testFormUrlEncoded1("Carson", 24);

        // @FieldMap
        // 實現(xiàn)的效果與上面相同涩咖,但要傳入Map
        Map<String, Object> map = new HashMap<>();
        map.put("username", "Carson");
        map.put("age", 24);
        Call<ResponseBody> call2 = service.testFormUrlEncoded2(map);
  • @Part & @PartMap

發(fā)送 Post請求 時提交請求的表單字段
與@Field的區(qū)別:功能相同海诲,但攜帶的參數(shù)類型更加豐富,包括數(shù)據(jù)流檩互,所以適用于 有文件上傳 的場景 與 @Multipart 注解配合使用

public interface GetRequest_Interface {

          /**
         * {@link Part} 后面支持三種類型特幔,{@link RequestBody}、{@link okhttp3.MultipartBody.Part} 闸昨、任意類型
         * 除 {@link okhttp3.MultipartBody.Part} 以外蚯斯,其它類型都必須帶上表單字段({@link okhttp3.MultipartBody.Part} 中已經(jīng)包含了表單字段的信息)薄风,
         */
        @POST("/form")
        @Multipart
        Call<ResponseBody> testFileUpload1(@Part("name") RequestBody name, @Part("age") RequestBody age, @Part MultipartBody.Part file);

        /**
         * PartMap 注解支持一個Map作為參數(shù),支持 {@link RequestBody } 類型拍嵌,
         * 如果有其它的類型遭赂,會被{@link retrofit2.Converter}轉(zhuǎn)換,如后面會介紹的 使用{@link com.google.gson.Gson} 的 {@link retrofit2.converter.gson.GsonRequestBodyConverter}
         * 所以{@link MultipartBody.Part} 就不適用了,所以文件只能用<b> @Part MultipartBody.Part </b>
         */
        @POST("/form")
        @Multipart
        Call<ResponseBody> testFileUpload2(@PartMap Map<String, RequestBody> args, @Part MultipartBody.Part file);

        @POST("/form")
        @Multipart
        Call<ResponseBody> testFileUpload3(@PartMap Map<String, RequestBody> args);
}

// 具體使用
 MediaType textType = MediaType.parse("text/plain");
        RequestBody name = RequestBody.create(textType, "Carson");
        RequestBody age = RequestBody.create(textType, "24");
        RequestBody file = RequestBody.create(MediaType.parse("application/octet-stream"), "這里是模擬文件的內(nèi)容");

        // @Part
        MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", "test.txt", file);
        Call<ResponseBody> call3 = service.testFileUpload1(name, age, filePart);
        ResponseBodyPrinter.printResponseBody(call3);

        // @PartMap
        // 實現(xiàn)和上面同樣的效果
        Map<String, RequestBody> fileUpload2Args = new HashMap<>();
        fileUpload2Args.put("name", name);
        fileUpload2Args.put("age", age);
        //這里并不會被當(dāng)成文件撰茎,因為沒有文件名(包含在Content-Disposition請求頭中)嵌牺,但上面的 filePart 有
        //fileUpload2Args.put("file", file);
        Call<ResponseBody> call4 = service.testFileUpload2(fileUpload2Args, filePart); //單獨處理文件
        ResponseBodyPrinter.printResponseBody(call4);
}
  • @Query和@QueryMap

用于 @GET 方法的查詢參數(shù)(Query = Url 中 ‘?’ 后面的 key-value)
如:url = http://www.println.net/?cate=android,其中龄糊,Query = cate
具體使用:配置時只需要在接口方法中增加一個參數(shù)即可:

   @GET("/")    
   Call<String> cate(@Query("cate") String cate);
}

// 其使用方式同 @Field與@FieldMap逆粹,這里不作過多描述
  • @Path

URL地址的缺省值,用@Path注解標(biāo)志要傳到url中{ }的變量
如:

public interface GetRequest_Interface {

        @GET("users/{user}/repos")
        Call<ResponseBody>  getBlog(@Path("user") String user );
        // 訪問的API是:https://api.github.com/users/{user}/repos
        // 在發(fā)起請求時, {user} 會被替換為方法的第一個參數(shù) user(被@Path注解作用)
    }
  • @Url

直接傳入一個請求的 URL變量 用于URL設(shè)置

public interface GetRequest_Interface {

        @GET
        Call<ResponseBody> testUrlAndQuery(@Url String url, @Query("showAll") boolean showAll);
       // 當(dāng)有URL注解時炫惩,@GET傳入的URL就可以省略
       // 當(dāng)GET僻弹、POST...HTTP等方法中沒有設(shè)置Url時,則必須使用 {@linlk Url}提供

}

數(shù)據(jù)解析器(Converter)

Retrofit支持多種數(shù)據(jù)解析方式
使用時需要在Gradle添加依賴

數(shù)據(jù)解析器 Gradle依賴
Gson implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
Jackson implementation 'com.squareup.retrofit2:converter-jackson:2.4.0'
Simple XML implementation 'com.squareup.retrofit2:converter-simplexml:2.0.2'
Protobuf implementation 'com.squareup.retrofit2:converter-protobuf:2.4.0'
Moshi implementation 'com.squareup.retrofit2:converter-moshi:2.4.0'
Wire implementation 'com.squareup.retrofit2:converter-wire:2.4.0'
Scalars implementation 'com.squareup.retrofit2:converter-scalars:2.4.0'

網(wǎng)絡(luò)請求適配器(CallAdapter)

  • Retrofit支持多種網(wǎng)絡(luò)請求適配器方式:guava他嚷、Java8和rxjava

使用時如使用的是 Android 默認(rèn)的 CallAdapter蹋绽,則不需要添加網(wǎng)絡(luò)請求適配器的依賴,否則則需要按照需求進(jìn)行添加 Retrofit 提供的 CallAdapter

  • 使用時需要在Gradle添加依賴:
網(wǎng)絡(luò)請求適配器 Gradle依賴
rxjava implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
Java8 implementation 'com.squareup.retrofit2:adapter-java8:2.4.0'
guava implementation 'com.squareup.retrofit2:adapter-guava:2.4.0'

發(fā)送網(wǎng)絡(luò)請求

封裝了 數(shù)據(jù)轉(zhuǎn)換筋蓖、線程切換的操作

//發(fā)送網(wǎng)絡(luò)請求(異步)
        call.enqueue(new Callback<Translation>() {
            //請求成功時回調(diào)
            @Override
            public void onResponse(Call<Translation> call, Response<Translation> response) {
                //請求處理,輸出結(jié)果
                response.body().show();
            }

            //請求失敗時候的回調(diào)
            @Override
            public void onFailure(Call<Translation> call, Throwable throwable) {
                System.out.println("連接失敗");
            }
        });

// 發(fā)送網(wǎng)絡(luò)請求(同步)
Response<Reception> response = call.execute();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末卸耘,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子粘咖,更是在濱河造成了極大的恐慌蚣抗,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瓮下,死亡現(xiàn)場離奇詭異翰铡,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)讽坏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進(jìn)店門锭魔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人路呜,你說我怎么就攤上這事迷捧。” “怎么了拣宰?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵党涕,是天一觀的道長。 經(jīng)常有香客問我巡社,道長,這世上最難降的妖魔是什么手趣? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任晌该,我火速辦了婚禮肥荔,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘朝群。我一直安慰自己燕耿,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布姜胖。 她就那樣靜靜地躺著誉帅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪右莱。 梳的紋絲不亂的頭發(fā)上蚜锨,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天,我揣著相機(jī)與錄音慢蜓,去河邊找鬼亚再。 笑死,一個胖子當(dāng)著我的面吹牛晨抡,可吹牛的內(nèi)容都是我干的氛悬。 我是一名探鬼主播,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼耘柱,長吁一口氣:“原來是場噩夢啊……” “哼如捅!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起调煎,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤镜遣,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后汛蝙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體烈涮,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年窖剑,在試婚紗的時候發(fā)現(xiàn)自己被綠了坚洽。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡西土,死狀恐怖讶舰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情需了,我是刑警寧澤跳昼,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站肋乍,受9級特大地震影響鹅颊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜墓造,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一堪伍、第九天 我趴在偏房一處隱蔽的房頂上張望锚烦。 院中可真熱鬧,春花似錦帝雇、人聲如沸涮俄。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽彻亲。三九已至,卻和暖如春吮廉,著一層夾襖步出監(jiān)牢的瞬間苞尝,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工茧痕, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留野来,地道東北人。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓踪旷,卻偏偏與公主長得像曼氛,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子令野,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,914評論 2 355

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