Android?OkHttp庫(kù)簡(jiǎn)單使用和封裝教程助你快速掌握網(wǎng)絡(luò)請(qǐng)求技能
OkHttp的封裝
由于是封裝我們可以吧OKHttp和Gson給結(jié)合起來(lái),那么我們?cè)趃radle文件添加以下的依賴
compile "com.squareup.okhttp:okhttp:2.4.0"
compile 'com.squareup.okio:okio:1.5.0'
compile "com.google.code.gson:gson:2.8.0"
①CallBack的創(chuàng)建
首選我們知道,當(dāng)接口請(qǐng)求成功或者失敗的時(shí)候我們需要將這個(gè)信息通知給用戶,那么我們就需要?jiǎng)?chuàng)建一個(gè)抽象類RequestCallBack,請(qǐng)求前、成功、失敗、請(qǐng)求后這幾個(gè)方法,創(chuàng)建OnBefore()、OnAfter()、OnError()、OnResponse()對(duì)應(yīng)
/**
* 在請(qǐng)求之前的方法,一般用于加載框展示
*
* @param request
*/
public void onBefore(Request request) {
}
/**
* 在請(qǐng)求之后的方法,一般用于加載框隱藏
*/
public void onAfter() {
}
/**
* 請(qǐng)求失敗的時(shí)候
*
* @param request
* @param e
*/
public abstract void onError(Request request, Exception e);
/**
*
* @param response
*/
public abstract void onResponse(T response);
由于我們每次想要的數(shù)據(jù)不一定,所以這里我們用<T>來(lái)接收想要裝成的數(shù)據(jù)格式,并通過(guò)反射得到想要的數(shù)據(jù)類型(一般是Bean、List)之類 ,所以RequestCallBack的整體代碼如下:
package com.qianmo.httprequest.http;
import com.google.gson.internal.$Gson$Types;
import com.squareup.okhttp.Request;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
* Created by wangjitao on 15/10/16.
* 抽象類,用于請(qǐng)求成功后的回調(diào)
*/
public abstract class ResultCallback<T> {
//這是請(qǐng)求數(shù)據(jù)的返回類型,包含常見(jiàn)的(Bean,List等)
Type mType;
public ResultCallback() {
mType = getSuperclassTypeParameter(getClass());
}
/**
* 通過(guò)反射想要的返回類型
*
* @param subclass
* @return
*/
static Type getSuperclassTypeParameter(Class<?> subclass) {
Type superclass = subclass.getGenericSuperclass();
if (superclass instanceof Class) {
throw new RuntimeException("Missing type parameter.");
}
ParameterizedType parameterized = (ParameterizedType) superclass;
return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);
}
/**
* 在請(qǐng)求之前的方法,一般用于加載框展示
*
* @param request
*/
public void onBefore(Request request) {
}
/**
* 在請(qǐng)求之后的方法,一般用于加載框隱藏
*/
public void onAfter() {
}
/**
* 請(qǐng)求失敗的時(shí)候
*
* @param request
* @param e
*/
public abstract void onError(Request request, Exception e);
/**
*
* @param response
*/
public abstract void onResponse(T response);
}
?、趯?duì)Get、Post方法的簡(jiǎn)單封裝
首先我們創(chuàng)建一個(gè)OkHttpClientManager類,由于是管理類,所以,單例加靜態(tài)對(duì)象搞起
private static OkHttpClientManager mInstance;
public static OkHttpClientManager getInstance() {
if (mInstance == null){
synchronized (OkHttpClientManager.class) {
if (mInstance == null) {
mInstance = new OkHttpClientManager();
}
}
}
return mInstance;
}
在創(chuàng)建Manager對(duì)象的時(shí)候我們要把OkHttp的一些參數(shù)配置一下,順便一提一下,由于我們我們異步get、post方法是運(yùn)行在子線程中,所以這里我們添加了分發(fā)的Handler mDelivery;,重寫(xiě)的OkHttpClientManager構(gòu)造方法如下:
private OkHttpClientManager() {
mOkHttpClient = new OkHttpClient();
mOkHttpClient.setConnectTimeout(10, TimeUnit.SECONDS);
mOkHttpClient.setWriteTimeout(10, TimeUnit.SECONDS);
mOkHttpClient.setReadTimeout(30, TimeUnit.SECONDS);
//cookie enabled
mOkHttpClient.setCookieHandler(new CookieManager(null, CookiePolicy.ACCEPT_ORIGINAL_SERVER));
mDelivery = new Handler(Looper.getMainLooper());
mGson = new Gson();
}
前面的外部調(diào)用對(duì)象封裝好了,這里我們開(kāi)始來(lái)封裝Get或Post方法,我這里以Post方法為例子,首先分析一下,post方法會(huì)有幾個(gè)參數(shù),參數(shù)一url,參數(shù)二參數(shù)params,參數(shù)三Callback(及我們上面的RequestCallBack)參數(shù)四flag(用于取消請(qǐng)求操作,可為空),基礎(chǔ)代碼如下:
/**
* 通用基礎(chǔ)的異步的post請(qǐng)求
* @param url
* @param callback
* @param tag
*/
public void postAsyn(String url, Param[] params, final ResultCallback callback, Object tag) {
Request request = buildPostFormRequest(url, params, tag);
deliveryResult(callback, request);
}
那么我們?cè)倏匆幌耫eliveryResult方法到底是干什么的
/**
* 請(qǐng)求回調(diào)處理方法并傳遞返回值
* @param callback Map類型請(qǐng)求參數(shù)
* @param request Request請(qǐng)求
*/
private void deliveryResult(ResultCallback callback, Request request) {
if (callback == null)
callback = DEFAULT_RESULT_CALLBACK;
final ResultCallback resCallBack = callback;
//UI thread
callback.onBefore(request);
mOkHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(final Request request, final IOException e) {
sendFailedStringCallback(request, e, resCallBack);
}
@Override
public void onResponse(final Response response) {
try {
final String responseMessage=response.message();
final String responseBody = response.body().string();
if(response.code()==200){
if (resCallBack.mType == String.class) {
sendSuccessResultCallback(responseBody, resCallBack);
} else {
Object o = mGson.fromJson(responseBody, resCallBack.mType);
sendSuccessResultCallback(o, resCallBack);
}
}else{
Exception exception=new Exception(response.code()+":"+responseMessage);
sendFailedStringCallback(response.request(), exception, resCallBack);
}
} catch (IOException e) {
sendFailedStringCallback(response.request(), e, resCallBack);
} catch (com.google.gson.JsonParseException e) {//Json解析的錯(cuò)誤
sendFailedStringCallback(response.request(), e, resCallBack);
}
}
});
}
可以看到,這個(gè)方法主要是發(fā)出請(qǐng)求并對(duì)請(qǐng)求后的數(shù)據(jù)開(kāi)始回調(diào),這樣我們就基本上封裝好了一個(gè)post方法了 ,把代碼這一部分的代碼貼出來(lái)看看
public class OkHttpClientManager {
private static final String TAG = "com.qianmo.httprequest.http.OkHttpClientManager";
private static OkHttpClientManager mInstance;
//默認(rèn)的請(qǐng)求回調(diào)類
private final ResultCallback<String> DEFAULT_RESULT_CALLBACK = new ResultCallback<String>(){
@Override
public void onError(Request request, Exception e) {}
@Override
public void onResponse(String response) {}
};
private OkHttpClient mOkHttpClient;
private Handler mDelivery;
private Gson mGson;
private GetDelegate mGetDelegate = new GetDelegate();
private PostDelegate mPostDelegate = new PostDelegate();
private DownloadDelegate mDownloadDelegate = new DownloadDelegate();
private OkHttpClientManager() {
mOkHttpClient = new OkHttpClient();
mOkHttpClient.setConnectTimeout(10, TimeUnit.SECONDS);
mOkHttpClient.setWriteTimeout(10, TimeUnit.SECONDS);
mOkHttpClient.setReadTimeout(30, TimeUnit.SECONDS);
//cookie enabled
mOkHttpClient.setCookieHandler(new CookieManager(null, CookiePolicy.ACCEPT_ORIGINAL_SERVER));
mDelivery = new Handler(Looper.getMainLooper());
mGson = new Gson();
}
public static OkHttpClientManager getInstance() {
if (mInstance == null){
synchronized (OkHttpClientManager.class) {
if (mInstance == null) {
mInstance = new OkHttpClientManager();
}
}
}
return mInstance;
}
/**
* 外部可調(diào)用的Post異步請(qǐng)求方法
* @param url 請(qǐng)求url
* @param params
* @param callback 請(qǐng)求完成后回調(diào)類
*/
public static void postAsyn(String url, Map<String, String> params, final ResultCallback callback) {
getInstance().getPostDelegate().postAsyn(url, params, callback, null);
}
/**
* 異步的post請(qǐng)求
* @param url
* @param params
* @param callback
* @param tag
*/
public void postAsyn(String url, Map<String, String> params, final ResultCallback callback, Object tag) {
Param[] paramsArr = map2Params(params);
postAsyn(url, paramsArr, callback, tag);
}
/**
* 通用基礎(chǔ)的異步的post請(qǐng)求
* @param url
* @param callback
* @param tag
*/
public void postAsyn(String url, Param[] params, final ResultCallback callback, Object tag) {
Request request = buildPostFormRequest(url, params, tag);
deliveryResult(callback, request);
}
/**
* 請(qǐng)求回調(diào)處理方法并傳遞返回值
* @param callback Map類型請(qǐng)求參數(shù)
* @param request Request請(qǐng)求
*/
private void deliveryResult(ResultCallback callback, Request request) {
if (callback == null)
callback = DEFAULT_RESULT_CALLBACK;
final ResultCallback resCallBack = callback;
//UI thread
callback.onBefore(request);
mOkHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(final Request request, final IOException e) {
sendFailedStringCallback(request, e, resCallBack);
}
@Override
public void onResponse(final Response response) {
try {
final String responseMessage=response.message();
final String responseBody = response.body().string();
if(response.code()==200){
if (resCallBack.mType == String.class) {
sendSuccessResultCallback(responseBody, resCallBack);
} else {
Object o = mGson.fromJson(responseBody, resCallBack.mType);
sendSuccessResultCallback(o, resCallBack);
}
}else{
Exception exception=new Exception(response.code()+":"+responseMessage);
sendFailedStringCallback(response.request(), exception, resCallBack);
}
} catch (IOException e) {
sendFailedStringCallback(response.request(), e, resCallBack);
} catch (com.google.gson.JsonParseException e) {//Json解析的錯(cuò)誤
sendFailedStringCallback(response.request(), e, resCallBack);
}
}
});
}
/**
* 處理請(qǐng)求成功的回調(diào)信息方法
* @param object 服務(wù)器響應(yīng)信息
* @param callback 回調(diào)類
*/
private void sendSuccessResultCallback(final Object object, final ResultCallback callback) {
mDelivery.post(() -> {
callback.onResponse(object);
callback.onAfter();
});
}
}
這樣我們就把Post方法封裝好了,同理Get方法,ok,現(xiàn)在我們可以來(lái)調(diào)用調(diào)用了,在調(diào)用之前我們可以對(duì)返回?cái)?shù)據(jù)格式再來(lái)封裝封裝,一般我們后臺(tái)返回的數(shù)據(jù)格式是類似如下:
{
"code": 200,
"data": {},
"message": "登錄成功"
}而data中有可能是對(duì)象,也有可能是數(shù)組,所以我們用兩個(gè)類來(lái)實(shí)現(xiàn)一下
package com.qianmo.httprequest.bean;
/**
* 服務(wù)端返回通用接收實(shí)體
* Created by wangjitao on 15/10/30.
*/
public class CommonResultBean<T> {
private String code;
private T data;
private String message;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
CommonResultListBean
package com.qianmo.httprequest.bean;
import java.util.List;
/**
* 服務(wù)端返回帶有List數(shù)據(jù)的通用接收實(shí)體
* Created by wangjitao on 15/12/1.
*/
public class CommonResultListBean<T> {
private String code;
private List<T> data;
private String message;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public List<T> getData() {
return data;
}
public void setData(List<T> data) {
this.data = data;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
ok,現(xiàn)在還是以上面我們登錄的接口為例子開(kāi)始我們的方法調(diào)用,返回的數(shù)據(jù)格式如圖所示

我們創(chuàng)建UserMenu.java類
package com.qianmo.httprequest.bean;
import java.util.List;
/**
* Created by wangjitao on 2016/12/21 0021.
* E-Mail:543441727@qq.com
* 用戶菜單權(quán)限按鈕
*/
public class UserMenu {
/**
* last_login_time : 2016-12-21 15:40:28
* member_id : 1
* modules : []
* phone : 18900532225
* real_name : 超級(jí)管理員
* role : {"role_id":1,"role_name":"超級(jí)管理員"}
* username : superadmin
*/
private String last_login_time;
private int member_id;
private String phone;
private String real_name;
/**
* role_id : 1
* role_name : 超級(jí)管理員
*/
private RoleBean role;
private String username;
/**
* module_code : 100
* module_id : 1
* module_name : 首頁(yè)
* pid : 0
* type : 1
* value : P_index
*/
private List<ModulesBean> modules;
public String getLast_login_time() {
return last_login_time;
}
public void setLast_login_time(String last_login_time) {
this.last_login_time = last_login_time;
}
public int getMember_id() {
return member_id;
}
public void setMember_id(int member_id) {
this.member_id = member_id;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getReal_name() {
return real_name;
}
public void setReal_name(String real_name) {
this.real_name = real_name;
}
public RoleBean getRole() {
return role;
}
public void setRole(RoleBean role) {
this.role = role;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public List<ModulesBean> getModules() {
return modules;
}
public void setModules(List<ModulesBean> modules) {
this.modules = modules;
}
public static class RoleBean {
private int role_id;
private String role_name;
public int getRole_id() {
return role_id;
}
public void setRole_id(int role_id) {
this.role_id = role_id;
}
public String getRole_name() {
return role_name;
}
public void setRole_name(String role_name) {
this.role_name = role_name;
}
}
public static class ModulesBean {
private String module_code;
private int module_id;
private String module_name;
private int pid;
private int type;
private String value;
public String getModule_code() {
return module_code;
}
public void setModule_code(String module_code) {
this.module_code = module_code;
}
public int getModule_id() {
return module_id;
}
public void setModule_id(int module_id) {
this.module_id = module_id;
}
public String getModule_name() {
return module_name;
}
public void setModule_name(String module_name) {
this.module_name = module_name;
}
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}
所以MainActivity代碼如下:
package com.qianmo.httprequest;
import android.os.Environment;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.qianmo.httprequest.bean.CommonResultBean;
import com.qianmo.httprequest.bean.UserMenu;
import com.qianmo.httprequest.http.IRequestCallBack;
import com.qianmo.httprequest.http.IRequestManager;
import com.qianmo.httprequest.http.OkHttpClientManager;
import com.qianmo.httprequest.http.RequestFactory;
import com.qianmo.httprequest.http.ResultCallback;
import com.squareup.okhttp.Call;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.FormEncodingBuilder;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class MainActivity extends AppCompatActivity implements OnClickListener {
private Handler handler;
private TextView tv_message;
private Button btn_login;
private ProgressBar progressBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_message = (TextView) findViewById(R.id.tv_message);
btn_login = (Button) findViewById(R.id.btn_login);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
handler = new Handler();
btn_login.setOnClickListener(this);
}
@Override
public void onClick(View view) {
progressBar.setVisibility(View.VISIBLE);
String url = "http://192.168.1.123:8081/api/login";
Map<String, String> params = new HashMap();
params.put("username", "superadmin");
params.put("pwd", "ba3253876aed6bc22d4a6ff53d8406c6ad864195ed144ab5c87621b6c233b548baeae6956df346ec8c17f5ea10f35ee3cbc514797ed7ddd3145464e2a0bab413");
OkHttpClientManager.postAsyn(url, params,
new ResultCallback<CommonResultBean<UserMenu>>() {
@Override
public void onError(Request request, Exception e) {
}
@Override
public void onResponse(CommonResultBean<UserMenu> response) {
if (response.getData() != null) {
UserMenu userMenu = response.getData();
tv_message.setText(userMenu.getReal_name());
progressBar.setVisibility(View.GONE);
}
}
});
}
}
這樣我們就可以簡(jiǎn)單的調(diào)用了,最后看一下我們的效果:

到此這篇關(guān)于Android OkHttp庫(kù)簡(jiǎn)單使用和封裝教程助你快速掌握網(wǎng)絡(luò)請(qǐng)求技能的文章就介紹到這了,更多相關(guān)Android OkHttp內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android 實(shí)現(xiàn)密碼輸入框動(dòng)態(tài)明文/密文切換顯示效果
在項(xiàng)目中遇到需要提供給用戶一個(gè)密碼輸入框明文/密文切換顯示的需求,今天小編借腳本之家平臺(tái)給大家分享下Android 實(shí)現(xiàn)密碼輸入框動(dòng)態(tài)明文/密文切換顯示效果,需要的朋友參考下2017-01-01
Android通過(guò)HttpURLConnection和HttpClient接口實(shí)現(xiàn)網(wǎng)絡(luò)編程
這篇文章主要介紹了Android通過(guò)HttpURLConnection和HttpClient接口實(shí)現(xiàn)網(wǎng)絡(luò)編程的相關(guān)資料,需要的朋友可以參考下2015-02-02
Android設(shè)計(jì)模式之適配器(Adapter)模式
這篇文章主要介紹了Android設(shè)計(jì)模式之適配器(Adapter)模式,以源碼解析的方式分析適配器模式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11
Android布局中g(shù)ravity與layout_gravity屬性說(shuō)明
這篇文章主要介紹了Android布局中g(shù)ravity與layout_gravity屬性說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01
談?wù)凙ndroid里的Context的使用實(shí)例
這篇文章主要介紹了談?wù)凙ndroid里的Context的使用實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2016-11-11
Android實(shí)現(xiàn)一個(gè)帶粘連效果的LoadingBar
Loading效果相信大家應(yīng)該都實(shí)現(xiàn)過(guò),最近發(fā)現(xiàn)了一個(gè)不錯(cuò)的效果,決定分享給大家,所以下面這篇文章主要給大家介紹了關(guān)于利用Android實(shí)現(xiàn)一個(gè)帶粘連效果的LoadingBar的相關(guān)資料,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-12-12

