Android模块化-----网络模块封装

在实际的应用开发中,常用到的网络框架有OkHttp、Retrofit、RxJava+RxAndroid,每个框架都有自己的优点:例如OkHttp,因为其特有的拦截器责任链模式,可以拦截请求和响应;Retrofit内部封装OkHttp,它更高效在于使用注解封装Http请求,在之前Retrofit中也使用过;RxJava的优势在于它的操作符,事件的转换。
每个框架都有自己的优点,因此通过整合全部的请求框架,来实现多域名、多环境、结构清晰的网络模块,因此在项目封装网络请求模块势在必行。
1、基础理论
首先先介绍一下Http中请求和响应的报文格式。
(1)get请求报文格式
Android模块化-----网络模块封装
文章图片

------第一部分:请求行
主要包括请求方法GET、URL(接口)、协议版本(Http1.0或者Http1.1)
------第二部分:请求头
Host:域名(www.xxxxx.xxx)、Connection(如果是Http1.1会默认是长连接 Keep Alive)、与Accept相关的字段(像Accept-Language、Accept-Encoding)…
(2)get请求响应报文
Android模块化-----网络模块封装
文章图片

------第一部分:响应行
状态码、状态码描述、协议版本
------第二部分:响应头
Server:服务器端的描述、Connection:长连接、响应的类型Content-type:json数据。。。。。。
------第三部分:响应体
装载响应数据
Post请求方式与get请求不同的是:请求报文格式中,请求的数据放在请求体中。
2、搭建网络模块
(1)Retrofit网络请求模块

implementation 'com.squareup.retrofit2:retrofit:2.7.1' implementation 'com.squareup.okhttp:okhttp:2.7.5' implementation 'com.squareup.retrofit2:converter-gson:2.7.1'

Retrofit retrofit = new Retrofit.Builder() .baseUrl(Constant.BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); INetworkApi iNetworkApi = retrofit.create(INetworkApi.class); Call call = iNetworkApi.getData(0); call.enqueue(new Callback() { @Override public void onResponse(Call call, Response response) { Log.e("TAG","response==="+response.body().toString()); }@Override public void onFailure(Call call, Throwable t) {} });

一般在应用中使用Retrofit就是这样的流程,在Model创建一个方法,请求这个方法在内部进行网络请求。
(2)添加日志拦截器
implementation 'com.squareup.okhttp3:logging-interceptor:4.4.0'

日志拦截器,主要是打印在网络请求时,请求和响应的过程,返回报文中的各个字段值。
public static OkHttpClient getOkHttpClient(){ OkHttpClient.Builder okhttpclient = new OkHttpClient.Builder(); if(iNetWorkRequiredInfo != null && iNetWorkRequiredInfo.isDebug()){ //http拦截,打印报文 HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); okhttpclient.addInterceptor(loggingInterceptor); } //添加拦截器 okhttpclient.addInterceptor(new CommonRequestInterceptor(iNetWorkRequiredInfo)); return okhttpclient.build(); }

(3)添加请求和响应的拦截器
在实际开发过程中,通常需要在请求的头部添加字段或者截取响应中的某些字段,同样也需要使用OkHttp的拦截器实现。
public class CommonRequestInterceptor implements Interceptor { private final INetWorkRequiredInfo netWorkRequiredInfo; public CommonRequestInterceptor(INetWorkRequiredInfo netWorkRequiredInfo){ this.netWorkRequiredInfo = netWorkRequiredInfo; } @NotNull @Override public Response intercept(@NotNull Chain chain) throws IOException { //创建请求 Request.Builder builder = chain.request().newBuilder(); //添加请求头 builder.addHeader("Content-Type","application/json; charset=UTF-8"); return chain.proceed(builder.build()); } }

public class CommonResponseInterceptor implements Interceptor { private final INetWorkRequiredInfo requiredInfo; public CommonResponseInterceptor(INetWorkRequiredInfo requiredInfo){ this.requiredInfo = requiredInfo; } @NotNull @Override public Response intercept(@NotNull Chain chain) throws IOException { //执行请求返回响应 Response response = chain.proceed(chain.request()); if(!response.header("Set-Cookie").isEmpty()){ //cookie字段有很多,只需要有JSessionId的字段 for (String header : response.headers("Set-Cookie")) { if (header.contains("JSESSIONID")) { //将Cookie保存在本地} } } return response; } }

(4)支持RxJava
RxJava的优点就不必在此多说,看代码吧。
Observable observable = iNetworkApi.getDataByRxJava(0); observable.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer() { @Override public void onSubscribe(Disposable d) {}@Override public void onNext(ArticleBean articleBeanLiveData) {}@Override public void onError(Throwable e) {}@Override public void onComplete() {} }); }

(5)优化架构
在观察者订阅之后,有4个方法拖在后面,不太美观,因此可以抽取一个抽象的Observer类,然后只需要做请求成功或者失败的回调。
public abstract class BaseObserver implements Observer { @Override public void onSubscribe(Disposable d) {} @Override public void onNext(T t) { onSuccess(t); } @Override public void onError(Throwable e) { onFailed(e); } @Override public void onComplete() {} protected abstract void onSuccess(T t); protected abstract void onFailed(Throwable e); }

.subscribe(new BaseObserver() { @Override protected void onSuccess(ArticleBean articleBeanLiveData) { Log.e("TAG","livedatahttps://www.it610.com/article/==="+articleBeanLiveData); }@Override protected void onFailed(Throwable e) {} });

(6)业务接口
在网络层中,主要封装网络请求、OkHttp拦截器、日志拦截等操作,具体的业务还是得在app中完成,所以之前在网络层中的api接口以及javabean类都必须放到业务模块。
那么对于Retrofit对象,就需要拿到app当中使用。
//保存Retrofit对象 private static HashMap,Retrofit> retrofitMap = new HashMap<>();

不用单例设计模式,使用HashMap存储Retrofit对也可以,key就是BaseUrl + service的名字,在调用同一个api的时候,如果之前已经创建了Retrofit对象,那么就直接从集合中拿。
public static Retrofit getRetrofit(Class service) { if(retrofitMap.get(Constant.BASE_URL + service.getName()) != null){ return retrofitMap.get(Constant.BASE_URL + service.getName()); }Retrofit retrofit = new Retrofit.Builder() .baseUrl(Constant.BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .client(getOkHttpClient()) .build(); //如果不存在,就将Retrofit添加到map集合 retrofitMap.put(Constant.BASE_URL + service.getName(),retrofit); return retrofit; }

//统一的接口调用 public static T getService(Class service){ return getRetrofit(service).create(service); }

(7)线程调度的封装
在业务层调用api时,需要做线程切换。
NetWorkApi.getService(INetworkApi.class).getDataByRxJava(0) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new BaseObserver() { @Override protected void onSuccess(ArticleBean articleBean) {}@Override protected void onFailed(Throwable e) {} });

这一部分是可以抽出来,使用compose来切换的,在compose方法中,是传入的ObservableTransformer,因此在网络模块中,创建一个线程调度的类。
//线程切换的封装 public static ObservableTransformer applyScheduler(final Observer observer){ return new ObservableTransformer() { @Override public ObservableSource apply(Observable upstream) { Observable observable = upstream.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); observable.subscribe(observer); return observable; } }; }

【Android模块化-----网络模块封装】在业务模块中使用compose就非常的简洁。
NetWorkApi.getService(INetworkApi.class).getDataByRxJava(0) //做线程切换的封装 .compose(NetWorkApi.applyScheduler(new BaseObserver() { @Override protected void onSuccess(ArticleBean articleBean) {} @Override protected void onFailed(Throwable e) {} }));

    推荐阅读