Android 訪問網(wǎng)絡(luò):方案二 OkHttp + Retrofit

本文使用登錄場景來簡單介紹 Android 應(yīng)用中使用 OkHttp + Retrofit 訪問網(wǎng)絡(luò)的用法氢哮。

  • 數(shù)據(jù)交換協(xié)議 HTTP
  • 數(shù)據(jù)交換格式 JSON
  • HTTP 請求方法 POST

使用 HTTP 訪問網(wǎng)絡(luò)的準(zhǔn)備工作固以,參見Android 訪問網(wǎng)絡(luò):方案一 OkHttp一文訪問網(wǎng)絡(luò)的準(zhǔn)備工作部分。

使用 OkHttp + Retrofit 訪問網(wǎng)絡(luò)


1.引入依賴

build.gradle(:app)

dependencies {
    ...
    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'

    implementation 'com.squareup.okhttp3:logging-interceptor:3.14.9'
}

2.定義網(wǎng)絡(luò)訪問接口

創(chuàng)建 UserService 接口汹胃,用來提供 User 模塊的網(wǎng)絡(luò)訪問服務(wù)。除了登錄 login() , 還可以在這里定義獲取用戶信息焦人,修改用戶名竖独,更換頭像等功能對應(yīng)的方法。
UserService.java

public interface UserService {

    @POST("user/login")
    Call<Result<String>> login(@Body LoginParam loginParam);

    // getUserDetail()

    // modifyUserName()

    // replaceAvatar()

}
方法注解 @POST
  1. 方法注解用于描述該請求的 HTTP 方法绷杜,@POST 表示該請求的方法為 POST 直秆。
  2. "user/login" 是請求的相對路徑,Retrofit 會將其和 baseUrl 拼接起來鞭盟,構(gòu)成完整的 URL 圾结。
  3. 比較常用的其他方法注解
    @GET
    @PUT
    @DELETE
方法參數(shù)注解 @Body
  1. 方法參數(shù)注解用于描述方法參數(shù)作為請求的什么內(nèi)容,@Body 表示把方法參數(shù)的序列化結(jié)果作為請求體齿诉。
  2. 比較常用的其他方法參數(shù)注解
    @Field 表示采用鍵值對的形式組織請求參數(shù)筝野,作為請求體。使用該注解時(shí)粤剧,需要為方法添加 @FormUrlEncoded 注解歇竟,設(shè)置 MIME type 為 application/x-www-urlencoded 。

@Field 使用示例

方法定義
@FormUrlEncoded
@POST("/")
Call<ResponseBody> example(
@Field("name") String name,
@Field("occupation") String occupation);

方法調(diào)用 foo.example("Bob Smith", "President")

請求體 name=Bob+Smith&occupation=President
注:多個(gè)請求參數(shù)使用 & 分隔抵恋,每個(gè)參數(shù)的名和值使用 = 連接焕议。"Bob Smith" 的空格替換為 + 。

LoginParam

LoginParam 是簡單的登錄請求參數(shù)類弧关,包含用戶名和密碼兩個(gè)屬性盅安。
LoginParam.java

public class LoginParam {

    public String userName;
    public String password;

    public LoginParam(String userName, String password){
        this.userName = userName;
        this.password = password;
    }

}
Result

Result 是網(wǎng)絡(luò)訪問結(jié)果類,包含 code, message, data 三個(gè)屬性世囊。
Result.java

public class Result<DATA> {

    private static final int HTTP_REQUEST_SUCCESS_CODE = 600;

    public int code;
    public String message;
    public DATA data;

    public boolean isSuccessful() {
        return code == HTTP_REQUEST_SUCCESS_CODE;
    }

    @NonNull
    @Override
    public String toString() {
        return "Result{" +
                "code=" + code +
                ", message='" + message + '\'' +
                ", data=" + data +
                '}';
    }

}

3. 創(chuàng)建 Retrofit 實(shí)例

  1. 創(chuàng)建 OkHttp 實(shí)例别瞭,添加日志攔截器,以便調(diào)試株憾。
OkHttpClient client = new OkHttpClient.Builder()
    .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
    .build();
  1. 創(chuàng)建 Retrofit 實(shí)例蝙寨,配置 baseUrl, 添加 ConverterFactory晒衩。
Retrofit retrofit = new Retrofit.Builder().
    baseUrl("http://192.168.43.218:8080/")
    .addConverterFactory(GsonConverterFactory.create())
    .client(client)
    .build();

4. 創(chuàng)建 Service 實(shí)例

UserService userService = retrofit.create(UserService.class);

5. 創(chuàng)建 Call 實(shí)例

Call<Result<String>> loginCall = userService.login(new LoginParam(userName, password));

假如這里 userName 的值為 "xumeng",password 的值為 "123456"墙歪,Retrofit 會使用 GsonConverter 將 LoginParam 對象轉(zhuǎn)為 JSON 字符串作為請求體听系。

請求體
{"password":"123456","userName":"xumeng"}

由于這一步比較簡單,通常的寫法是和下一步連起來箱亿,將 Call 的實(shí)例作為匿名對象來使用跛锌。

userService.login(new LoginParam(userName, password)).enqueue(new Callback<Result<String>>(){...});

6. 向服務(wù)端發(fā)送 HTTP 請求

  • Call 可以調(diào)用 execute() 發(fā)起同步請求,也可以調(diào)用 enqueue(Callback<T>) 發(fā)起異步請求届惋。本文采用異步方式發(fā)送請求髓帽。
    Call 實(shí)例入隊(duì),創(chuàng)建 Callback 實(shí)例脑豹,用于處理網(wǎng)絡(luò)訪問結(jié)果
loginCall.enqueue(new Callback<Result<String>>() {
    @Override
    public void onResponse(@NonNull Call<Result<String>> call, @NonNull Response<Result<String>> response) {
                
    }

    @Override
    public void onFailure(@NonNull Call<Result<String>> call, @NonNull Throwable t) {

    }
});

7. 在 Callback 的 onResponse() 中處理網(wǎng)絡(luò)訪問結(jié)果

  • Retrofit 會為我們從后臺線程切換到主線程郑藏,所以在 onResponse() 方法中無需考慮線程切換的問題。
  • Retrofit 會使用我們配置的 ConverterFactory 將響應(yīng)體的 JSON 數(shù)據(jù)轉(zhuǎn)換為 Result<> 類的實(shí)例瘩欺,調(diào)用 response.body() 方法即可獲取必盖。
@Override
public void onResponse(@NonNull Call<Result<String>> call, @NonNull Response<Result<String>> response) {
    Result<String> result = response.body();
    if (result == null) {
        onFailure(call, new Throwable("body is null"));
        return;
    }
    Toast.makeText(LoginActivity.this, result.message, Toast.LENGTH_SHORT).show();
    if (result.isSuccessful()) {
        Log.i(TAG, "token : " + result.data);
        // save token
        // start activity
    }
}


測試設(shè)備參數(shù)

  • 型號:vivo Y66L
  • 操作系統(tǒng):Funtouch OS 3.0(Android 6.0.1)

參考資料

  1. Square : Retrofit
  2. MDN : HTTP request methods POST

代碼

XuMeng-0 / android-study

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市俱饿,隨后出現(xiàn)的幾起案子歌粥,更是在濱河造成了極大的恐慌,老刑警劉巖拍埠,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件失驶,死亡現(xiàn)場離奇詭異,居然都是意外死亡枣购,警方通過查閱死者的電腦和手機(jī)嬉探,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來棉圈,“玉大人涩堤,你說我怎么就攤上這事》竹” “怎么了胎围?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長德召。 經(jīng)常有香客問我白魂,道長,這世上最難降的妖魔是什么氏捞? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮冒版,結(jié)果婚禮上液茎,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好捆等,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布滞造。 她就那樣靜靜地躺著,像睡著了一般栋烤。 火紅的嫁衣襯著肌膚如雪谒养。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天明郭,我揣著相機(jī)與錄音买窟,去河邊找鬼。 笑死薯定,一個(gè)胖子當(dāng)著我的面吹牛始绍,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播话侄,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼亏推,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了年堆?” 一聲冷哼從身側(cè)響起吞杭,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎变丧,沒想到半個(gè)月后芽狗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡锄贷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年译蒂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谊却。...
    茶點(diǎn)故事閱讀 40,110評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡柔昼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出炎辨,到底是詐尸還是另有隱情捕透,我是刑警寧澤,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布碴萧,位于F島的核電站乙嘀,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏破喻。R本人自食惡果不足惜虎谢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望曹质。 院中可真熱鬧婴噩,春花似錦擎场、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至章蚣,卻和暖如春站欺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背纤垂。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工矾策, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人洒忧。 一個(gè)月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓蝴韭,卻偏偏與公主長得像,于是被迫代替她去往敵國和親熙侍。 傳聞我的和親對象是個(gè)殘疾皇子榄鉴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,047評論 2 355

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