源码https://github.com/bkhacker/business
3-1 网络请求组件—OkHttp简单使用
开发思路
我们把网络请求以及后面的视频播放SDK封装到这里,创建的时候要选择library,不是创建module。当我们编写这个lib内所有代码,就封装好我们自己的SDK,可以直接拿到app中去用了,不用再去开发通用的繁琐的东西了。
包结构
我们先来发送最简单的一个okhttp请求
public class BaseOkhttpTestActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
/**
* 用okhttp发送一个最基本的请求
*/
private void sendRequest() {
//创建OkhttpClient对象
OkHttpClient mOkHttpClient = new OkHttpClient();
//创建一个Request
final Request request = new Request.Builder()
.url("https://www.baidu.com/")
.build();
//new call
Call call = mOkHttpClient.newCall(request);
//请求加入调度
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
}
我们可以看到上面,发送一个请求就有如此多的代码,如果我们写在activity中,肯定是不合理的,也造成了代码冗余,所以我们就要把它封装起来。
3-2 网络请求组件—封装思路讲解
开发思路
3-3 网络请求组件—Request封装
封装的SDK包结构
我们发送请求,先去写一个封装参数的类,将所有请求参数到hashmap,RequestParams.java -->request
package com.youdu.okhttp.request;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author vision
*/
public class RequestParams {
public ConcurrentHashMap<String, String> urlParams = new ConcurrentHashMap<String, String>();
public ConcurrentHashMap<String, Object> fileParams = new ConcurrentHashMap<String, Object>();
/**
* Constructs a new empty {@code RequestParams} instance.
*/
public RequestParams() {
this((Map<String, String>) null);
}
/**
* Constructs a new RequestParams instance containing the key/value string
* params from the specified map.
*
* @param source the source key/value string map to add.
*/
public RequestParams(Map<String, String> source) {
if (source != null) {
for (Map.Entry<String, String> entry : source.entrySet()) {
put(entry.getKey(), entry.getValue());
}
}
}
/**
* Constructs a new RequestParams instance and populate it with a single
* initial key/value string param.
*
* @param key the key name for the intial param.
* @param value the value string for the initial param.
*/
public RequestParams(final String key, final String value) {
this(new HashMap<String, String>() {
{
put(key, value);
}
});
}
/**
* Adds a key/value string pair to the request.
*
* @param key the key name for the new param.
* @param value the value string for the new param.
*/
public void put(String key, String value) {
if (key != null && value != null) {
urlParams.put(key, value);
}
}
public void put(String key, Object object) throws FileNotFoundException {
if (key != null) {
fileParams.put(key, object);
}
}
public boolean hasParams() {
if(urlParams.size() > 0 || fileParams.size() > 0){
return true;
}
return false;
}
}
接下来我们写公共request
package youdu.com.imooccsdk.okhttp.request;
import java.util.Map;
import okhttp3.FormBody;
import okhttp3.Request;
/**
* 作者:yeweizheng on 2017/2/20 11:06
* 包名:youdu.com.imooccsdk.okhttp.request
* 文件名:imoocvuansdk
* 描述:接受请求参数,为我们生成request对象
*/
public class CommonRequest {
/**
* @param url
* @param params
* @return 通过传入的参数返回一个Get类型的请求
*/
public static Request createGetRequest(String url, RequestParams params) {
StringBuilder urlBuilder = new StringBuilder(url).append("?");
if (params != null) {
for (Map.Entry<String, String> entry : params.urlParams.entrySet()) {
urlBuilder.append(entry.getKey()).append("=")
.append(entry.getValue())
.append("&");
}
}
return new Request.Builder().url(urlBuilder.substring(0, urlBuilder.length() - 1))
.get().build();
}
/**
* @param url
* @param params
* @return 通过传入的参数返回一个Post类型的请求
*/
public static Request createPostRequest(String url, RequestParams params) {
FormBody.Builder mFormBodyBuild = new FormBody.Builder();
if (params != null) {
for (Map.Entry<String, String> entry : params.urlParams.entrySet()) {
//将请求参数遍历添加到我们的请求构建类中
mFormBodyBuild.add(entry.getKey(), entry.getValue());
}
}
//通过请求构件类的build方法获取到真正的请求体对象
FormBody mFormBody = mFormBodyBuild.build();
return new Request.Builder().url(url).post(mFormBody).build();
}
}
有了request对象之后,我们要去创建一个发送request的client。
package youdu.com.imooccsdk.okhttp;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import youdu.com.imooccsdk.okhttp.https.HttpsUtils;
import youdu.com.imooccsdk.okhttp.listener.DisposeDataHandle;
import youdu.com.imooccsdk.okhttp.response.CommonJsonCallback;
/**
* 作者:yeweizheng on 2017/2/20 15:10
* 包名:youdu.com.imooccsdk.okhttp
* 文件名:imoocvuansdk
* 描述:用来发送get post请求的工具类,包括设置一些请求的公共参数
*/
public class CommonOkHttpClient {
public static int TIME_OUT = 30;
public static OkHttpClient mOkHttpClient;
//每个请求的请求参数都是相同,比如超时时间,使用static为这个示例配置一致参数
//为我们的client去配置参数了
static {
//创建我们的client对象的构建者
OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder();
//为构建着填充参数
okHttpBuilder.connectTimeout(TIME_OUT, TimeUnit.SECONDS);
okHttpBuilder.readTimeout(TIME_OUT, TimeUnit.SECONDS);
okHttpBuilder.writeTimeout(TIME_OUT, TimeUnit.SECONDS);
//允许重定向
okHttpBuilder.followRedirects(true);
//HTTPS支持
okHttpBuilder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
/**
* trust all the https point
*/
okHttpBuilder.sslSocketFactory(HttpsUtils.initSSLSocketFactory(), HttpsUtils.initTrustManager());
//生成Client对象
mOkHttpClient = okHttpBuilder.build();
}
/**
* 发送具体的http/https请求
*
* @param request
* @param commonCallback
* @return Call
*/
public static Call sendRequest(Request request, CommonJsonCallback commonCallback) {
Call call = mOkHttpClient.newCall(request);
call.enqueue(commonCallback);
return call;
}
/**
* 通过构造好的Request,Callback去发送请求
*
* @param request
* @param
*/
public static Call get(Request request, DisposeDataHandle handle) {
Call call = mOkHttpClient.newCall(request);
call.enqueue(new CommonJsonCallback(handle));
return call;
}
public static Call post(Request request, DisposeDataHandle handle) {
Call call = mOkHttpClient.newCall(request);
call.enqueue(new CommonJsonCallback(handle));
return call;
}
}
原来回调时callback,下面我们来写个发送的测试方法,所以我们要再把回调封装一下
private void test() {
CommonOkHttpClient.sendRequest(CommonRequest.createGetRequest("http://www.imooc.com/", null),
new CommonJsonCallback(new DisposeDataHandle(new DisposeDataListener() {
@Override
public void onSuccess(Object responseObj) {
}
@Override
public void onFailure(Object reasonObj) {
//1.异常 2.数据解析 3.数据转发 再对callback进行封装
}
}))
);
}
3-5 网络请求组件—Response封装
CommonJsonCallback
listener包下
package youdu.com.imooccsdk.okhttp.listener;
/**
* 作者:yeweizheng on 2017/2/20 15:55
* 包名:youdu.com.imooccsdk.okhttp.listener
* 文件名:imoocvuansdk
* 描述: 自定义事件监听
*/
public interface DisposeDataListener {
/**
* 请求成功回调事件处理
*/
public void onSuccess(Object responseObj);
/**
* 请求失败回调事件处理
*/
public void onFailure(Object reasonObj);
}
package youdu.com.imooccsdk.okhttp.listener;
/**
* 作者:yeweizheng on 2017/2/20 20:37
* 包名:youdu.com.imooccsdk.okhttp.listener
* 文件名:imoocvuansdk
* 描述:对json的预处理 字节码。。。
*/
public class DisposeDataHandle {
public DisposeDataListener mListener = null;
public Class<?> mClass = null;
public String mSource = null;
public DisposeDataHandle(DisposeDataListener listener) {
this.mListener = listener;
}
public DisposeDataHandle(DisposeDataListener listener, Class<?> clazz) {
this.mListener = listener;
this.mClass = clazz;
}
public DisposeDataHandle(DisposeDataListener listener, String source) {
this.mListener = listener;
this.mSource = source;
}
}
response包下
package youdu.com.imooccsdk.okhttp.response;
import android.os.Handler;
import android.os.Looper;
import org.json.JSONObject;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;
import youdu.com.imooccsdk.adutil.ResponseEntityToModule;
import youdu.com.imooccsdk.okhttp.exception.OkHttpException;
import youdu.com.imooccsdk.okhttp.listener.DisposeDataListener;
import youdu.com.imooccsdk.okhttp.listener.DisposeDataHandle;
/**
* 作者:yeweizheng on 2017/2/20 20:59
* 包名:youdu.com.imooccsdk.okhttp.response
* 文件名:imoocvuansdk
* 描述:专门处理JSON的回调
*/
public class CommonJsonCallback implements Callback {
protected final String RESULT_CODE = "ecode";
// 有返回则对于http请求来说是成功的,但还有可能是业务逻辑上的错误
protected final int RESULT_CODE_VALUE = 0;
protected final String ERROR_MSG = "emsg";
protected final String EMPTY_MSG = "";
protected final String COOKIE_STORE = "Set-Cookie";
/**
* 自定义异常类型
*/
protected final int NETWORK_ERROR = -1;
protected final int JSON_ERROR = -2;
protected final int OTHER_ERROR = -3;
private Handler mDeliveryHandler;//进行消息转发
private DisposeDataListener mListener;
private Class<?> mClass;
public CommonJsonCallback(DisposeDataHandle handle) {
this.mListener = handle.mListener;
this.mClass = handle.mClass;
this.mDeliveryHandler = new Handler(Looper.getMainLooper());
}
//请求失败处理 抛到应用层
@Override
public void onFailure(Call call, final IOException ioexception) {
mDeliveryHandler.post(new Runnable() {
@Override
public void run() {
mListener.onFailure(new OkHttpException(NETWORK_ERROR, ioexception));
}
});
}
@Override
public void onResponse(Call call, Response response) throws IOException {
final String result = response.body().string();
mDeliveryHandler.post(new Runnable() {
@Override
public void run() {
handleResponse(result);
}
});
}
private void handleResponse(Object responseObj) {
//为了保证代码的健壮性
if (responseObj == null || responseObj.toString().trim().equals("")) {
mListener.onFailure(new OkHttpException(NETWORK_ERROR, EMPTY_MSG));
return;
}
try {
JSONObject result = new JSONObject(responseObj.toString());
if (result.has(RESULT_CODE)) {
//从json对象中取出
if (result.getInt(RESULT_CODE) == RESULT_CODE_VALUE) {
if (mClass == null) {
mListener.onSuccess(responseObj);
} else {
//即,需要我们将json转换为实体对象
Object obj = ResponseEntityToModule.parseJsonObjectToRealmModel(
result, mClass);
//标明正确的转为了实体对象
if (obj != null) {
mListener.onSuccess(obj);
} else {
//返回的不是合法的json
mListener.onFailure(new OkHttpException(JSON_ERROR, EMPTY_MSG));
}
}
} else {
//将服务器返回的异常回调到应用层去处理
mListener.onFailure(new OkHttpException(OTHER_ERROR, result.get(RESULT_CODE)));
}
}
} catch (Exception e) {
mListener.onFailure(new OkHttpException(OTHER_ERROR, e.getMessage()));
}
}
}
新的测试
网友评论