三三要成為安卓糕手
一:OkHttp介紹
OkHttp 是一個開源的、強大且高效的 HTTP 客戶端庫,主要用于在 Java后端和Android 項目中進行網絡請求。
//在gradle中添加依賴
com.squareup.okhttp3:okhttp:4.12.0
二:GET請求
/*** 使用OkHttp發起get請求*/private void sendGetRequest(){String id = etUserId.getText().toString();String urlAddress = "http://titok.fzqq.fun/addons/cms/api.user/userInfo?user_id=" + id + "&type=archives";//創建OkHttpClient實例對象,用于發起請求OkHttpClient okHttpClient = new OkHttpClient.Builder().connectTimeout(10,TimeUnit.SECONDS).readTimeout(30, TimeUnit.SECONDS).build();//設置請求屬性,比如地址,方法屬性Request request = new Request.Builder().url(urlAddress).get().build();//發起單個請求Call call = okHttpClient.newCall(request);//接收響應Callback callback = new Callback() {@Overridepublic void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {runOnUiThread(new Runnable() {@Overridepublic void run() {if(response.isSuccessful()){//響應成功try {String result = response.body().string();Log.i(TAG, "run: result" + result);//把json字符串轉化為對象UserInfoQuery userInfoQuery = new Gson().fromJson(result, UserInfoQuery.class);String msg = "當前的用戶名是:" + userInfoQuery.getData().getUser().getNickname();Toast.makeText(OkHttpActivity.this,msg,Toast.LENGTH_SHORT).show();} catch (IOException e) {throw new RuntimeException(e);}}else{Toast.makeText(OkHttpActivity.this,"網絡請求失敗"+response.code(),Toast.LENGTH_SHORT).show();}}});}@Overridepublic void onFailure(@NonNull Call call, @NonNull IOException e) {runOnUiThread(new Runnable() {@Overridepublic void run() {Toast.makeText(OkHttpActivity.this,"網絡請求失敗",Toast.LENGTH_SHORT).show();}});}};call.enqueue(callback);}
1:大致步驟
- 使用builder去創建OkHttpClient實例對象,設置一些連接的屬性:常見連接超時,數據讀取超時
- 使用builder設置請求屬性:常見url,get方法
- 調用newCall發起單次請求,傳入request參數,使用enqueue異步線程
- new Callback();重寫接口中的onResponse方法和onFailure方法
- 方法中的內部邏輯,對于ui的處理要在主線程中進行,調用runOnUiThread(new Runnable接口,重寫run方法)
2:一些細節
- 我們一般不會直接new一個request,而是選擇一個底下的一個builder的東西
(1)內部回調接口
在 OkHttp 中,call.enqueue(callback)
并非 “把響應丟進 call 里”,而是通過回調機制實現異步請求的結果處理
Call
對象是對一個 HTTP 請求的封裝,調用enqueue(callback)
時,其實是向Call 注冊了一個回調接口。- OkHttp 會在后臺線程執行網絡請求,當請求完成(成功或失敗)后,會自動調用
onResponse
或onFailure
方法,并將響應結果(Response
對象)作為參數傳入。
(2)次線程轉主線程
接口中重寫的onResponse方法和onFailure方法內部的代碼,涉及到UI應該要回到主線程中去進行
回到主線程去完成ui(彈窗操作)
(3)enqueue方法的說明
“enqueue” 把…… 加入隊列
在 Java 中,enqueue
方法的簽名是 void enqueue(Callback responseCallback)
,它接收一個 Callback
類型的參數,Callback
是 OkHttp 中定義的一個接口,包含兩個抽象方法:
onResponse(Call call, Response response)
:當 HTTP 請求成功完成,且服務器返回了響應時,該方法會被調用,response
參數包含了從服務器獲取到的響應信息,比如響應碼、響應頭、響應體等;call
參數則是當前正在處理結果的這個請求對應的Call
對象。onFailure(Call call, IOException e)
:當請求執行過程中發生錯誤,比如網絡連接失敗、超時等情況,這個方法會被調用。
(4)response.body().string()
主要作用是將 ResponseBody
的內容以字符串形式讀取出來。
它會根據響應體的編碼(Content-Type
),把響應體中的字節數據解碼為字符串。并非用toString方法
(5)toString () 方法
默認的 toString()
方法返回的是 ResponseBody
類的名稱以及對象的哈希碼等信息,而不是響應體中的實際內容。
例如:可能返回類似 okhttp3.ResponseBody@12345678
這樣的字符串,其中 okhttp3.ResponseBody
是類名,@12345678
是對象的哈希碼表示 。
(6)TimeUnit 時間單位
在設置超時方面,可以用安卓內部定義好的時間的單位常量
3:效果
三:POST請求
/*** POST請求*/private void sendPostRequest(){String loginUrl = "http://titok.fzqq.fun/addons/cms/api.login/login";OkHttpClient okHttpClient = new OkHttpClient.Builder().connectTimeout(10,TimeUnit.SECONDS).readTimeout(30,TimeUnit.SECONDS).build();String account = etUserName.getText().toString();String password = etPassword.getText().toString();//用Gson去拼接一個請求體String jsonBody = new Gson().toJson(new ReqLogin(account, password));//請求體的數據格式是Json,編碼格式是utf-8MediaType mediaType = MediaType.get("application/json;charset=utf-8");RequestBody requestBody = RequestBody.create(jsonBody, mediaType);//構建請求Request request = new Request.Builder().url(loginUrl).post(requestBody).build();//發起請求Call call = okHttpClient.newCall(request);Callback callback = new Callback() {@Overridepublic void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {runOnUiThread(new Runnable() {@Overridepublic void run() {if(response.isSuccessful()){try {String json = response.body().string();Log.i(TAG, "run: " + json);//把json數據轉化為對象,獲取其中的屬性ResLogin resLogin = new Gson().fromJson(json, ResLogin.class);String msg = resLogin.getMsg();int userId = resLogin.getData().getUser_id();Toast.makeText(OkHttpActivity.this,msg + ".歡迎用戶" + userId, Toast.LENGTH_SHORT).show();} catch (IOException e) {throw new RuntimeException(e);}}else {Toast.makeText(OkHttpActivity.this,"登錄失敗",Toast.LENGTH_SHORT).show();}}});}@Overridepublic void onFailure(@NonNull Call call, @NonNull IOException e) {runOnUiThread(new Runnable() {@Overridepublic void run() {Toast.makeText(OkHttpActivity.this,"POST登錄請求失敗",Toast.LENGTH_SHORT).show();}});}};call.enqueue(callback);}
1:流程
- 設置連接屬性
- ui上獲取數據,Gson.toJson拼接字符串請求體
- 設置請求體數據格式
- 構建請求
- 發起請求
- 處理響應
2:一些細節
(1) 設計body參數
(2)MediaType.get(“application/json;charset=utf-8”);
媒體類型
用于定義請求體或響應體的數據格式和編碼方式,是處理 JSON 數據時的常見用法。
3:登錄效果
四:快捷生成JSON對應的對象
商業場景中是會創建一個實體類對象的;而非進行字符串拼接
//先用日志獲取json體
String json = response.body().string();
Log.i(TAG, "run: " + json);//在依據日志生成java對象,通過對象去獲取其中的屬性
new Gson().fromJson(json, ResLogin.class)
package com.xlong.networkbyjavaproject.bean;public class ResLogin {/*** code : 1* msg : 登錄成功* time : 1756263107* data : {"token":"6c45ff48-c7ef-4666-918e-26dabb214746","user_id":4}*/private int code;private String msg;private String time;private DataBean data;public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public String getTime() {return time;}public void setTime(String time) {this.time = time;}public DataBean getData() {return data;}public void setData(DataBean data) {this.data = data;}public static class DataBean {/*** token : 6c45ff48-c7ef-4666-918e-26dabb214746* user_id : 4*/private String token;private int user_id;public String getToken() {return token;}public void setToken(String token) {this.token = token;}public int getUser_id() {return user_id;}public void setUser_id(int user_id) {this.user_id = user_id;}}
}