网络请求框架封装(NetWorkUtils)
效果图:
项目描述:
网络请求框架二次封装,目前完成了基于OkHttp的get/post/postJson/uploadFile/downloadFile等功能开发,支持扩展,底层实现可自由切换;
- 扩展请继承ExecutorFactory实现具体的IExecutor即可,底层可以是OkHttp,也可以是HttpClient或者URLConnection;
使用方式:
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
//在程序入口进行工厂初始化,默认的为okhttp的实现工厂
NetWorkUtils.init(new OkHttpExecutorFactory());
}
}
//get方式请求
private void doGet() {
String url = "http://127.0.0.1:8080/test/test";
RequestParams params = new RequestParams.Builder().url(url).method(Method.GET).params("key1", "hello").params("key2", "doGet").tag(this).build();
NetWorkUtils.getInstance().doStart(params, callback);
}
//post方式请求
private void doPost() {
String url = "http://127.0.0.1:8080/test/test";
RequestParams params = new RequestParams.Builder().url(url).method(Method.POST).params("key1", "hello").params("key2", "doPost").tag(this).build();
NetWorkUtils.getInstance().doStart(params, callback);
}
//postJson方式请求
private void doPostJson() {
String url = "http://127.0.0.1:8080/test/test";
String body = "{ \"key1\":\"hello\",\"key2\":\"doPostJson\" }";
RequestParams params = new RequestParams.Builder().url(url).method(Method.POST_JSON).body(body).tag(this).build();
NetWorkUtils.getInstance().doStart(params, callback);
}
//文件上传
private void doUploadFile() {
String url = "http://127.0.0.1:8080/test/upload";
String filePath = Environment.getExternalStorageDirectory().getPath() + File.separator + "atlas-master.zip";
RequestParams params = new RequestParams.Builder().url(url).method(Method.UPLOAD).files("fileKey", new File(filePath)).tag(this).build();
NetWorkUtils.getInstance().doStart(params, callback);
}
//文件下载
private void doDownload() {
String url = "http://127.0.0.1:8080/test/download";
String filePath = Environment.getExternalStorageDirectory().getPath() + File.separator + "atlas-master.zip";
RequestParams params = new RequestParams.Builder().url(url).method(Method.DOWNLOAD).downLoadFilePath(filePath).tag(this).build();
NetWorkUtils.getInstance().doStart(params, callback);
}
//请求回调,主线程中进行
private ICallBack callback = new ICallBack() {
@Override
public void onStart() {
Log.d(NetWorkUtils.class.getSimpleName(), "网络开始加载");
}
@Override
public void onComplite() {
Log.d(NetWorkUtils.class.getSimpleName(), "网络加载完成");
}
@Override
public void onError(Exception e) {
Log.d(NetWorkUtils.class.getSimpleName(), "出现错误");
}
@Override
public void onSuccess(Object tag, String result) {
Log.d(NetWorkUtils.class.getSimpleName(), "result = "+result);
/**
* 可以根据不同的tag来解析数据
* if(tag.equest("doGet")){
*
* }else if(tag.equest("doPost")){
*
* }
* ............
*/
}
@Override
public void onProgress(float progress) {
Log.d(NetWorkUtils.class.getSimpleName(), "上传或下载进度 : "+progress);
}
};
//支持根据tag来取消具体的网络请求
protected void onDestroy() {
NetWorkUtils.getInstance().cancleRequest(this);
super.onDestroy();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
技术要点:
- 抽象工厂模式
- 构建者模式
- OkHttp使用
- OkHttp上传与下载的进度监听
- 线程回调
背景介绍:
网络请求在app开发中占据很重要的角色,也算是核心技术要点之一。github上也有很多著名的开源库,如Xutils,AsyncHttpClient,Okhttp等等。我相信很多人如同我一样,习惯性的拿这些开源的加入到自己的项目中,但当有一天,因为某些原因我们需要对网络层进行一次切换,那么是不是问题就变的严重了,我们需要改大量的代码来满足这次更改。为了避免这样的问题发生,我们需要对网络层进行二次包装一下;
项目结构:
- IExecutor 网络请求接口类,定义了get/post/postJson/uploadFile/downloadFile等;
- ExecutorFactory IExecutor的创建工厂,抽象类;
- OkHttpExecutor 实现了IExecutor的接口,实现了具体的get/post/postJson/uploadFile/downloadFile等方法;
- OkHttpExecutorFactory 实现了ExecutorFactory,并返回了OkHttpExecutor实例;
- MainHandler UI线程回调;
- RequestParams 请求参数,采用构建者模式;
- NetWorkUtils 网络请求工具类,单利,全局唯一 ;
注意:默认的okhttp enqueue(call)后,是回调在子线成中的;
执行流程,代码分析:
NetWorkUtils.init(new OkHttpExecutorFactory()) 后发生了什么?
public static IExecutor executor;
public static NetWorkUtils mInstance;
private NetWorkUtils(ExecutorFactory factory) {
executor = factory.create();
}
/**
* init networkutils
* 设置底层使用哪种网络实现,目前只实现了OkHttpExecutorFactory,如果想扩展的话请继承ExecutorFactory自行实现
* @param factory
*/
public static void init(ExecutorFactory factory) {
if (mInstance == null) {
synchronized (NetWorkUtils.class) {
if (mInstance == null) {
mInstance = new NetWorkUtils(factory);
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
我们看到进行了NetWorkUtils单利的初始化,并通过工厂获取到了IExecutor的具体实现类;
OkHttpExecutorFactory继承自ExecutorFactory,并实现了create抽象方法:
public class OkHttpExecutorFactory extends ExecutorFactory {
@Override
public IExecutor create() {
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(String message) {
Log.d(NetWorkUtils.class.getSimpleName(), message);
}
});
//建造者模式,生成配置对象
OkhttpConfig config = new OkhttpConfig.Builder().retryOnConnectionFailure(false).connectTimeout(10000).readTimeout(5000).writeTimeout(5000).interceptors(httpLoggingInterceptor).build();
return new OkHttpExecutor(config);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
通过OkhttpConfig构建者创建了OkHttpExecutor 并返回;
OkHttpExecutor实现了IExecutor接口并实现了接口中所有的方法,所以这个才是具体的网络请求实现:
public static OkHttpClient mClient;
public static final Map<Object, ArrayList<Call>> calls = new HashMap<>();
public OkHttpExecutor(OkhttpConfig config) {
//配置okhttpclient,全局唯一
OkHttpClient.Builder builder = new OkHttpClient.Builder().retryOnConnectionFailure(config.retryOnConnectionFailure).connectTimeout(config.connectTimeout, TimeUnit.MILLISECONDS)
.readTimeout(config.readTimeout, TimeUnit.MILLISECONDS).writeTimeout(config.writeTimeout, TimeUnit.MILLISECONDS);
if (config.cache != null) {
builder.cache(config.cache);
}
if (config.x509TrustManager != null && config.sslSocketFactory != null) {
builder.sslSocketFactory(config.sslSocketFactory, config.x509TrustManager);
}
if (config.interceptors != null && config.interceptors.size() > 0) {
for (int i = 0; i < config.interceptors.size(); i++) {
builder.addInterceptor(config.interceptors.get(i));
}
}
if (config.networkInterceptors != null && config.networkInterceptors.size() > 0) {
for (int i = 0; i < config.networkInterceptors.size(); i++) {
builder.addNetworkInterceptor(config.networkInterceptors.get(i));
}
}
mClient = builder.build();
}
@Override
public void doGet(RequestParams requestParams, ICallBack callback) {
callback.onStart();
Request request = new Request.Builder().url(OkhttpUtils.getUrlWithParams(requestParams)).get().headers(OkhttpUtils.getHeaders(requestParams)).tag(requestParams.tag).build();
Call call = mClient.newCall(request);
call.enqueue(new OkhttpCallback(requestParams));
cacheCall(requestParams, call);
}
@Override
public void doPost(RequestParams requestParams, ICallBack callback) {
callback.onStart();
Request request = new Request.Builder().url(requestParams.url).post(OkhttpUtils.getPostBody(requestParams)).headers(OkhttpUtils.getHeaders(requestParams)).tag(requestParams.tag).build();
Call call = mClient.newCall(request);
call.enqueue(new OkhttpCallback(requestParams));
cacheCall(requestParams, call);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
部分代码,具体的请查看源码;
在构造器中,我们通过OkhttpConfig实例化了一个OkHttpClient,并在doGet,doPost中使用OkHttpClient进行具体的网络请求,如果对okhttp不熟悉的同学,可以百度先学习下okhttp;
注意,ICallBack是我们自定义的callback,因为前面我提到过okhttp的回调是在子线成中进行的,所以我们有必要把它变为UI线程回调;
OkhttpCallback这个是我们继承自okhttp的Callback,然后在里面进行UI线程的切换,最后在回调到我们自己的ICallBack的;
OkhttpCallback 继承自okhttp的Callback:
public class OkhttpCallback implements Callback {
public static final Handler handler = new MainHandler(Looper.getMainLooper());
RequestParams requestParams;
public OkhttpCallback(RequestParams requestParams) {
this.requestParams = requestParams;
}
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
TempleteBean templeteBean = new TempleteBean();
templeteBean.call = call;
templeteBean.e = e;
templeteBean.requestParams = requestParams;
Message.obtain(handler, MainHandler.FAILD, templeteBean).sendToTarget();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
TempleteBean templeteBean = new TempleteBean();
templeteBean.call = call;
templeteBean.response = response;
templeteBean.requestParams = requestParams;
//downloadfile
if (requestParams.method.equals(Method.DOWNLOAD)) {
downLoadFile(templeteBean, response);
}
Message.obtain(handler, MainHandler.SUCCESS, templeteBean).sendToTarget();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
我们使用了TempleteBean进行数据的封装,并通过MainHandler发送到了UI线程中;
new MainHandler(Looper.getMainLooper()) 传入UI线程的looper即可回调在UI线程中;
MainHandler 继承自安卓系统中的Handler:
public class MainHandler extends Handler {
public static final int SUCCESS = 101;
public static final int FAILD = 102;
public static final int PROGRESS = 103;
public MainHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case SUCCESS:
onSuccess(msg);
break;
case FAILD:
onFaild(msg);
break;
case PROGRESS:
onProgress(msg);
break;
}
}
private void onSuccess(Message msg) {
TempleteBean bean = (TempleteBean) msg.obj;
RequestParams requestParams = bean.requestParams;
ICallBack callback = requestParams.callback;
Response response = bean.response;
if (!response.isSuccessful()) {
Log.d(NetWorkUtils.class.getSimpleName(), "!response.isSuccessful()" +response.code());
return;
}
if (requestParams.method.equals(Method.DOWNLOAD)) {
callback.onSuccess(requestParams.tag, requestParams.downLoadFilePath);
callback.onComplite();
return;
}
try {
String result = response.body().string();
Log.d(NetWorkUtils.class.getSimpleName(), result);
callback.onSuccess(requestParams.tag, result);
} catch (Exception e) {
e.printStackTrace();
callback.onError(e);
}
callback.onComplite();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
执行结果最终会进入到这个handler中,而这个handler是UI线程的,所以我们通过TempleteBean 获取到数据,在将结果回调到我们自己定义地的callback中;
至此,整个请求流程就完成了,然后我们回头看下NetWorkUtils;
NetWorkUtils 请求工具类,也是单利的,全局唯一的,我们在程序入口init的时候进行了单利的初始化:
public void doStart(RequestParams params, ICallBack callBack) {
if (params == null || callBack == null) return;
params.callback = callBack;
switch (params.method) {
case GET:
executor.doGet(params, callBack);
break;
case POST:
executor.doPost(params, callBack);
break;
case POST_JSON:
executor.doPostJson(params, callBack);
break;
case UPLOAD:
executor.doUploadFile(params, callBack);
break;
case DOWNLOAD:
executor.doDownLoad(params, callBack);
break;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
我们NetWorkUtils.getInstance().doStart(params,callback)即可发起网络请求;
还没有评论,来说两句吧...