案头见蠹鱼,犹胜凡俦侣。这篇文章主要讲述App 组件化/模块化之路——如何封装网络请求框架相关的知识,希望能为你提供帮助。
在 App 开发中网络请求是每个开发者必备的开发库,也出现了许多优秀开源的网络请求库App 组件化/模块化之路——如何封装网络请求框架
在 App 开发中网络请求是每个开发者必备的开发库,也出现了许多优秀开源的网络请求库。例如
- okhttp
- retrofit
- android-async-http
因此我们构建的网络请求框架要可以解决以下问题:
- 分离业务与网络请求代码
- 网络库可以很容易的被替换
- 网络库可以很方便的复用
封装第三方网络请求接口一般来说,目前绝大部分 App 的数据请求都是使用 HTTP 协议,而数据交换的协议使用 json 格式。因此可以封装一个通用的请求接口。(当然还有其他一些协议,例如微信的 mars ,但是封装的思路是一致的,本文为了简单说明,暂时使用通用网络请求框架,不排除以后会对 mars 的封装)
首先预览一下框架结构
文章图片
IRequest这个类封装了网络请求的通用接口,定义请求接口
doRequest()
、获取请求连接 getUrl()
、获取请求方法 getHttpMethod()
等。public interface IRequest { enum HttpMethod { GET, POST, PUT, DELETE } //... 为了减少代码的篇幅,省略一些对本文说明不重要的片段,本文代码可以在 //https://github.com/wecodexyz/Componentization 获取到 void addParams(Map< String, String> params); String getUrl(); Pair< Integer, String> doRequest(); boolean isSupportCache(); void addHeader(String key, String value); HttpMethod getHttpMethod(); //... 为了减少代码的篇幅,省略一些对本文说明不重要的片段,本文代码可以在 //https://github.com/wecodexyz/Componentization 获取到 }
Request这个类是个抽象类,对
IRequest
的实现。目前是一个简单封装的实现。RequestWrapper这个类是一个泛型类,继承于
Request
并对第三方请求库的封装。例如本文就是对 okhttp
的封装,而泛型 T 对象就是请求得到的具体数据类型。如果要对其他请求库进行封装,就可以参考这个类的实现。注意这个类封装是纯粹的网络请求,不应该包含业务类相关的代码。否则无解决上文提出的三个问题。
public abstract class RequestWrapper extends Request {//... 为了减少代码的篇幅,省略一些对本文说明不重要的片段,本文代码可以在 //https://github.com/wecodexyz/Componentization 获取到@Override public Pair< Integer, String> doRequest() { Pair< Integer, String> result = new Pair< > (ERROR_NETWORK, ""); okhttp3.Request request = null; if (getHttpMethod() == HttpMethod.POST) { request = requestBuilder().url(getUrl()).post(requestBody()).build(); } else { request = requestBuilder().url(getUrlWithParams()).build(); } try { Response response = mClient.newCall(request).execute(); if (response.isSuccessful()) { result = new Pair< > (response.code(), response.body().string()); } else { result = new Pair< > (response.code(), response.message()); } } catch (IOException e) { Log.e(TAG, e.getMessage()); } return result; }//... 为了减少代码的篇幅,省略一些对本文说明不重要的片段,本文代码可以在 //https://github.com/wecodexyz/Componentization 获取到}
关键的代码是在
doRequest()
方法中,该方法实现了网络请求的代码,返回一个 Pair<
Integer,String>
对象,该对象的 first
属性是一个请求 code
,用于标识网络请求码(即是网络请求返回的200,404,301等)。而 second
就是网络请求的数据。BaseTextRequest这个类就是网络请求框架提供给业务类使用的一个接口。本文一开始就提出来 json 作为交互数据请求的协议。那么此类的封装就有利于业务数据的访问。
public abstract class BaseTextRequest< T> extends RequestWrapper {public BaseTextRequest(Context context) { super(context); }public Flowable< T> request() { return Flowable.fromCallable(new Callable< Pair< Integer, String> > () { @Override public Pair< Integer, String> call() throws Exception { Pair< Integer, String> result = doRequest(); return result; } }).flatMap(new Function< Pair< Integer, String> , Publisher< T> > () { @Override public Publisher< T> apply(@NonNull Pair< Integer, String> pair) throws Exception { if (isSuccessful(pair.first)) { return Flowable.just(onRequestFinish(pair.second)); } return Flowable.just(onRequestError(pair.first, pair.second)); } }); }@Override public boolean isSupportCache() { return true; }protected abstract T onRequestFinish(String result); protected abstract T onRequestError(int code, String message); }
由于请求网络是耗时的操作,rxjava2 来实现网络请求异步操作。
request
是对 RequestWrapper.doRequest() 方法的封装,并得到一个 Flowable
对象。同时定义了 onRequestFinish()
和 onRequestError()
两个方法。这两个方法就是具体业务类要处理的逻辑。
SimpleTextRequest假设有一个请求业务数据接口,返回数据是一个字符串。那么我们使用我们的框架就是这样来使用。本文例子是请求我们项目中的 README.md 的内容。用起来非常简单,只要继承于 BaseTextRequest,并实现
getUrl()
、 onRequestFinish()
onRequestError()
、 getHttpMethod()
这几个方法。注意严格来说这是一个业务类,所以是不应该放在 core 目录下的。
public class SimpleTextRequest extends BaseTextRequest< String> {public SimpleTextRequest(Context context, Map< String, String> params) { super(context); addParams(params); }@Override public String getUrl() { return "https://raw.githubusercontent.com/wecodexyz/Componentization/master/README.md"; }@Override public HttpMethod getHttpMethod() { return HttpMethod.GET; }@Override protected String onRequestFinish(String result) { //这里可以实现对 json 数据的解析,例如使用 JSONObject //对象解析具体的业务 return result; }@Override protected String onRequestError(int code, String message) { return message; } }
测试请求框架
request = new SimpleTextRequest(this, null); request.request() .subscribeOn(Schedulers.computation()) .observeOn(androidSchedulers.mainThread()) .subscribe(new Consumer< String> () { @Override public void accept(@NonNull String s) throws Exception { textView.setText(s); //这里返回接口请求的数据 } }, new Consumer< Throwable> () { @Override public void accept(@NonNull Throwable throwable) throws Exception { textView.setText(throwable.getMessage()); } });
本文运行的结果
文章图片
项目地址:https://github.com/wecodexyz/Componentization
微信关注我们,可以获取更多
【App 组件化/模块化之路——如何封装网络请求框架】
文章图片
推荐阅读
- Androidproject文件下assets目录与res目录的差别
- Android 5.1 Settings源代码简要分析
- Android消息机制
- android各种组件的监听器
- 安卓中遮罩图片的处理
- Androidc/c++ 应用向linux 平台迁移执行
- Android系统之路(初识MTK) ------ OTA打包ROM安装系统img等到ZIP
- android_handler
- Android 最火的高速开发框架AndroidAnnotations使用具体解释