公司app应用一直使用okhttp,虽然它确实好用,但是经年日久,使用时的不方便越来越多,比如重复代码过多,内存泄露不好控制,调用时参数过多等等。
还是决定痛下杀手,早点除掉这个顽疾。
So,有了这次网络层重新架构,感觉还算满意,现在列出一下过程:
1、首选看一下对外公开的网络层工具 AppConnecter:
/**网络层工具类*/
public class AppConnecter {
public static int CONNNET_TIMEOUT = 30; //超时设置
private static AppConnecter appConnecter; //单例对象
private RequestInterface mServer; //Retrofit2网络接口
private String mInitServerUrl; //请求域名中的主机名 如https://m.test.com
private final OkHttpClient client; //实际的请求主体 OkHttpClient
//初始化httpserver
private AppConnecter() {
OkHttpClient.Builder builder = new OkHttpClient().newBuilder(); //创建OkHttpClient
try {
builder.sslSocketFactory(createSSLSocketFactory()); //创建httpsClient
builder.hostnameVerifier(new TrustAllHostnameVerifier());
} catch (Exception e) {
}
builder.connectTimeout(CONNNET_TIMEOUT, TimeUnit.SECONDS); //设置网络超时
builder.readTimeout(CONNNET_TIMEOUT, TimeUnit.SECONDS);
builder.addInterceptor(new RequestInterceptor()); //OkHttp请求拦截器
client = builder.build();
mInitServerUrl = "https://m.test.com";
mServer = getServer();
}
private RequestInterface getServer() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(mInitServerUrl)
.client(client)
.addConverterFactory(ScalarsConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
return retrofit.create(RequestInterface.class); //自定义的网络接口
}
public static AppConnecter getInsatnce() { //单例 不用多说
if (appConnecter == null) {
synchronized (AppConnecter.class) {
if (appConnecter == null) {
appConnecter = new AppConnecter();
}
}
}
return appConnecter;
}
//用于切换网路请求的线程,observeOn是指定回调线程
Observable.Transformer schedulersTransformer() {
return new Observable.Transformer() {
@Override
public Observable call(Object observable) {
return ((Observable) observable)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(Schedulers.immediate());
}
};
}
/**
* 发送Post请求
*/
public Observable reqPostWithRx(String postUrl, Map postparams, PublishSubject lifecycleSubject) {
if (postparams == null) {
postparams = new HashMap<String, String>();
}
//防止内存创建的Observable,当call返回true的时候,终止rx的所有消息发送
Observable<ActivityLifeCycleEvent> compareLifecycleObservable =
lifecycleSubject.takeFirst(new Func1<Integer, Boolean>() {
@Override
public Boolean call(Integer integer) {
return integer.equals(ActivityLifeCycleEvent.STOP);
}
});
//发送请求
return mServer.queryRxPostUrl(postUrl, postparams).compose(schedulersTransformer()).takeUntil(compareLifecycleObservable);
}
/**
*发送Get请求
*/
public Observable reqGetWithRx(String url, Map<String, String> params, PublishSubject lifecycleSubject) {
if (params == null) {
params = new HashMap<String, String>();
}
//防止内存创建的Observable,当call返回true的时候,终止rx的所有消息发送
Observable<ActivityLifeCycleEvent> compareLifecycleObservable =
lifecycleSubject.takeFirst(new Func1<Integer, Boolean>() {
@Override
public Boolean call(Integer integer) {
boolean isStop = integer.equals(ActivityLifeCycleEvent.STOP);
return isStop;
}
});
//发送请求
return mServer.queryRxGetUrl(url, params).compose(schedulersTransformer()).takeUntil(compareLifecycleObservable);
}
这个类公布出来的就2个 : reqGetWithRx(用于get) reqPostWithRx (用于post)
它们返回的对象都是 Observable (Rx的关键核心类),用它可以做一系列的不同操作,什么排序,过滤等等,你想怎么弄它就怎么弄。它就是发送网络请求后,服务端返回的结果。
compareLifecycleObservable这个对象,十分关键,它就是为了防止我们android中经常容易犯错的那个内存泄露而设置的。我们在activity基类中统一新建lifecycleSubject。
它在哪使用呢?
就是在我们的本地界面activity finish的时候,
public void finish() {
lifecycleSubject.onNext(ActivityLifeCycleEvent.STOP);
super.finish();
}
这样它就会帮我们把当前页面所有的请求filish掉,怎么样,省心吧!
2、接着我们来看看RequestInterceptor(请求拦截器)
这个RequestInterceptor,其实是OkHttp自带的拦截器,我们只要继承okhttp3.Interceptor就可以了。
然后覆盖它的intercept方法,在这个方法里,做一些针对URL的操作,比如编码,签名,加密等
3、然后就是RequestInterface,自定义的网络接口
public interface RequestInterface {
//结合RxJava的Post请求
@FormUrlEncoded
@POST("{url}")
Observable<String> queryRxPostUrl(@Path("url") String url, @FieldMap Map<String, String> params);
//结合RxJava的get请求
@GET("{url}")
Observable<String> queryRxGetUrl(@Path("url") String url, @QueryMap Map<String,String> params);
}
这样调用的时候,我们传的参数,只需要 与功能相关的接口名称与参数了。
4、还需要定义一个Rx的网络回调订阅者Subscriber
这个类主要是用于统一处理返回的字符串解析,我们给它加上泛型,就可以统一解析成需要的数据对象。
public abstract class BaseSubscriber<T> extends Subscriber {
public final void onNext(final Object o) {
String result = (String) o;
//此处转换成我们需要的数据对象
Type type = ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
final T bean = JSON.parseObject(result, type); //假定返回的数据是json格式
...
onSuccess
onFailed
onError
5、最后我们统一在Activity的基类中增加通用方法
//BaseBean:自定义的数据对象基类
//ReqBean:自定义的网络请求参数对象
public <T extends BaseBean> void reqByGet(ReqBean reqBean, BaseSubscriber<T> reqCallBack) {
AppConnecter.getInsatnce().queryGetWithRx(reqBean.url, reqBean.getLastParams(), lifecycleSubject)
.subscribe(reqCallBack);
}
做了这么多,终于到了享受的时候了,很简单,一句代码搞定:
String url = "/test/test.do";
reqByGet(new ReqBean(url, new String[][]{{"参数1", "参数值"}}), new BaseSubscriber<XxxBean>(){
@Override
public void onSuccess(XxxBean sKeyBean) {
//此处处理相关业务
}
@Override
public void onFailed(String code, String msg) {
//错误处理
}
});
大功告成了~~~~!
(但其实它还是有明显的问题,大家有没有发现呢?
就是返回的Observable,是依赖第三方框架的,这个东东要是以后替换或者升级时,Rx改动了它,那就麻烦大了
所以,最好的办法是自定义一个接口,来包装Observable)