Android OkHttp的简单使用和封装详解

1,昨天把okHttp仔细的看了一下,以前都是调用同事封装好了的网络框架,直接使用很容易,但自己封装却不是那么简单,还好,今天就来自我救赎一把,就和大家写写从最基础的OKHttp的简单get、post的使用,再到它的封装。

2,OkHttp的简单使用

首先我们创建一个工程,并在布局文件中添加三个控件,TextView(用于展示获取到json后的信息)、Button(点击开始请求网络)、ProgressBar(网络加载提示框)

①简单的异步Get请求

第一步,创建OKHttpClient对象

第二步,创建Request请求

第三步,创建一个Call对象

第四步,将请求添加到调度中

不多说,直接上代码:

//okHttp的基本使用 --- get方法

String url = "https://api.douban.com/v2/movie/top250?start=0&count=10";

//1,创建OKHttpClient对象

OkHttpClient mOkHttpClient = new OkHttpClient();

//2,创建一个Request

Request request = new Request.Builder().url(url).build();

//3,创建一个call对象

Call call = mOkHttpClient.newCall(request);

//4,将请求添加到调度中

call.enqueue(new Callback() {

@Override

public void onFailure(Request request, IOException e) {

}

@Override

public void onResponse(Response response) throws IOException {

if (response.isSuccessful()) {

final String message = response.body().string();

handler.post(new Runnable() {

@Override

public void run() {

tv_message.setText(message);

progressBar.setVisibility(View.GONE);

}

});

}

}

});

效果如下:

5cb84286c18d2c73d336d711d9ead202.gif

注意,由于我们调用的enqueue()方法,是运行在网络线程中的,所以当我们得到json数据后想要获取更新UI的话,可以开使用handle.post()方法在run方法里面更新UI。

② 简单的异步Post请求

这里的Post请求我们以最常见的注册登录来举例。post请求的步骤和get是相似的只是在创建Request的 时候将服务器需要的参数传递进去.

代码如下:

String url = "http://192.168.1.123:8081/api/login";

//1,创建OKhttpClient对象

OkHttpClient mOkHttpClient = new OkHttpClient();

//2,创建Request

RequestBody formBody = new FormEncodingBuilder()

.add("username", "superadmin")

.add("pwd", "ba3253876aed6bc22d4a6ff53d8406c6ad864195ed144ab5c87621b6c233b548baeae6956df346ec8c17f5ea10f35ee3cbc514797ed7ddd3145464e2a0bab413")

.build();

Request request = new Request.Builder().url(url).post(formBody).build();

//3,创建call对象并将请求对象添加到调度中

mOkHttpClient.newCall(request).enqueue(new Callback() {

@Override

public void onFailure(Request request, IOException e) {

}

@Override

public void onResponse(Response response) throws IOException {

Log.i("wangjitao", response.body().string());

}

});

看一下我们服务器的断点

c790d4ec2db4665b3421c3c00eb23544.png

可以看到我们服务器的确拿到了我们传递参数,再看一下我们请求后拿到的数据

b15c9cde5db5c95e3360a836b3a4a396.png

ok,这样的话我们的post方法就没什么问题了

3,OkHttp的封装

由于是封装我们可以吧OKHttp和Gson给结合起来,那么我们在gradle文件添加以下的依赖

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的创建

首选我们知道,当接口请求成功或者失败的时候我们需要将这个信息通知给用户,那么我们就需要创建一个抽象类RequestCallBack,请求前、成功、失败、请求后这几个方法,创建OnBefore()、OnAfter()、OnError()、OnResponse()对应

/**

* 在请求之前的方法,一般用于加载框展示

*

* @param request

*/

public void onBefore(Request request) {

}

/**

* 在请求之后的方法,一般用于加载框隐藏

*/

public void onAfter() {

}

/**

* 请求失败的时候

*

* @param request

* @param e

*/

public abstract void onError(Request request, Exception e);

/**

*

* @param response

*/

public abstract void onResponse(T response);

由于我们每次想要的数据不一定,所以这里我们用来接收想要装成的数据格式,并通过反射得到想要的数据类型(一般是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.

* 抽象类,用于请求成功后的回调

*/

public abstract class ResultCallback {

//这是请求数据的返回类型,包含常见的(Bean,List等)

Type mType;

public ResultCallback() {

mType = getSuperclassTypeParameter(getClass());

}

/**

* 通过反射想要的返回类型

*

* @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]);

}

/**

* 在请求之前的方法,一般用于加载框展示

*

* @param request

*/

public void onBefore(Request request) {

}

/**

* 在请求之后的方法,一般用于加载框隐藏

*/

public void onAfter() {

}

/**

* 请求失败的时候

*

* @param request

* @param e

*/

public abstract void onError(Request request, Exception e);

/**

*

* @param response

*/

public abstract void onResponse(T response);

}

②对Get、Post方法的简单封装

首先我们创建一个OkHttpClientManager类,由于是管理类,所以,单例加静态对象搞起

private static OkHttpClientManager mInstance;

public static OkHttpClientManager getInstance() {

if (mInstance == null){

synchronized (OkHttpClientManager.class) {

if (mInstance == null) {

mInstance = new OkHttpClientManager();

}

}

}

return mInstance;

}

在创建Manager对象的时候我们要把OkHttp的一些参数配置一下,顺便一提一下,由于我们我们异步get、post方法是运行在子线程中,所以这里我们添加了分发的 Handler mDelivery;,重写的OkHttpClientManager构造方法如下:

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();

}

前面的外部调用对象封装好了,这里我们开始来封装Get或Post方法,我这里以Post方法为例子,首先分析一下,post方法会有几个参数,参数一url,参数二参数params,参数三Callback(及我们上面的RequestCallBack)参数四flag(用于取消请求操作,可为空),基础代码如下:

/**

* 通用基础的异步的post请求

* @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);

}

那么我们再看一下deliveryResult方法到底是干什么的

/**

* 请求回调处理方法并传递返回值

* @param callback Map类型请求参数

* @param request Request请求

*/

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解析的错误

sendFailedStringCallback(response.request(), e, resCallBack);

}

}

});

}

可以看到,这个方法主要是发出请求并对请求后的数据开始回调,这样我们就基本上封装好了一个post方法了  ,把代码这一部分的代码贴出来看看

public class OkHttpClientManager {

private static final String TAG = "com.qianmo.httprequest.http.OkHttpClientManager";

private static OkHttpClientManager mInstance;

//默认的请求回调类

private final ResultCallback DEFAULT_RESULT_CALLBACK = new ResultCallback(){

@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;

}

/**

* 外部可调用的Post异步请求方法

* @param url 请求url

* @param params

* @param callback 请求完成后回调类

*/

public static void postAsyn(String url, Map params, final ResultCallback callback) {

getInstance().getPostDelegate().postAsyn(url, params, callback, null);

}

/**

* 异步的post请求

* @param url

* @param params

* @param callback

* @param tag

*/

public void postAsyn(String url, Map params, final ResultCallback callback, Object tag) {

Param[] paramsArr = map2Params(params);

postAsyn(url, paramsArr, callback, tag);

}

/**

* 通用基础的异步的post请求

* @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);

}

/**

* 请求回调处理方法并传递返回值

* @param callback Map类型请求参数

* @param request Request请求

*/

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解析的错误

sendFailedStringCallback(response.request(), e, resCallBack);

}

}

});

}

/**

* 处理请求成功的回调信息方法

* @param object 服务器响应信息

* @param callback 回调类

*/

private void sendSuccessResultCallback(final Object object, final ResultCallback callback) {

mDelivery.post(() -> {

callback.onResponse(object);

callback.onAfter();

});

}

}

这样我们就把Post方法封装好了,同理Get方法,ok,现在我们可以来调用调用了,在调用之前我们可以对返回数据格式再来封装封装,一般我们后台返回的数据格式是类似如下:

{

"code": 200,

"data": {},

"message": "登录成功"

}

而data中有可能是对象,也有可能是数组,所以我们用两个类来实现一下

CommonResultBean

package com.qianmo.httprequest.bean;

/**

* 服务端返回通用接收实体

* Created by wangjitao on 15/10/30.

*/

public class CommonResultBean {

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;

/**

* 服务端返回带有List数据的通用接收实体

* Created by wangjitao on 15/12/1.

*/

public class CommonResultListBean {

private String code;

private List data;

private String message;

public String getCode() {

return code;

}

public void setCode(String code) {

this.code = code;

}

public List getData() {

return data;

}

public void setData(List data) {

this.data = data;

}

public String getMessage() {

return message;

}

public void setMessage(String message) {

this.message = message;

}

}

ok,现在还是以上面我们登录的接口为例子开始我们的方法调用,返回的数据格式如图所示

036f8d13d079e676f32adce1eb5044e5.png

我们创建UserMenu.java类

package com.qianmo.httprequest.bean;

import java.util.List;

/**

* Created by wangjitao on 2016/12/21 0021.

* E-Mail:543441727@qq.com

* 用户菜单权限按钮

*/

public class UserMenu {

/**

* last_login_time : 2016-12-21 15:40:28

* member_id : 1

* modules : []

* phone : 18900532225

* real_name : 超级管理员

* role : {"role_id":1,"role_name":"超级管理员"}

* username : superadmin

*/

private String last_login_time;

private int member_id;

private String phone;

private String real_name;

/**

* role_id : 1

* role_name : 超级管理员

*/

private RoleBean role;

private String username;

/**

* module_code : 100

* module_id : 1

* module_name : 首页

* pid : 0

* type : 1

* value : P_index

*/

private List 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 getModules() {

return modules;

}

public void setModules(List 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 params = new HashMap();

params.put("username", "superadmin");

params.put("pwd", "ba3253876aed6bc22d4a6ff53d8406c6ad864195ed144ab5c87621b6c233b548baeae6956df346ec8c17f5ea10f35ee3cbc514797ed7ddd3145464e2a0bab413");

OkHttpClientManager.postAsyn(url, params,

new ResultCallback>() {

@Override

public void onError(Request request, Exception e) {

}

@Override

public void onResponse(CommonResultBean response) {

if (response.getData() != null) {

UserMenu userMenu = response.getData();

tv_message.setText(userMenu.getReal_name());

progressBar.setVisibility(View.GONE);

}

}

});

}

}

这样我们就可以简单的调用了,最后看一下我们的效果:

188f8ec7eb36dd3fb7088d098315ef71.gif

See You Next Time···

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐