前言
现在的app都必不可少会用到网络请求,android原生也带有http请求的api,这里我们暂不讲,我们主要讲开源的网络请求解决方案,拥抱开源,本文在rxJava+retrofit+okhttp基础上分享如何封装集成适合于组件化开发的网络库
。rxJava+retrofit+okhttp的详细用法大家可以自行查找相关资料。
说明:此文章适用于服务端采用微服务结构,如用户相关的采用USER服务(举例:主机请求地址为http://user.api.test.io),照片相关的采用IMG服务(举例:主机请求地址为http://img.api.test.io),客户端可切换不同的开发环境,如内网测试环境、外网测试环境,线上环境等,比如USER服务的内网测试环境主机请求地址为http://user.api.test.io,外网测试环境主机请求地址http://uat.user.api.test.org。
准备
- 在AndroidManifest.xml申明网络权限
<uses-permission android:name="android.permission.INTERNET" />
在app下的build.gradle申明相关依赖
implementation "io.reactivex.rxjava2:rxjava:2.2.8"
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
implementation 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
implementation 'com.squareup.okhttp3:okhttp:3.12.0'
implementation 'com.google.code.gson:gson:2.8.5'
自定义订阅者ResourceSubscriber
没有加载提示
/**
* 作者:lpx on 2020/3/20 10:27
* Email : 1966353889@qq.com
* Describe:没有加载提示的订阅者(结合网络请求使用)
* update on 2020/3/23 15:06
*/
public class QuietSubscriber<T> extends ResourceSubscriber<T> {
private OnNext<T> mNextListener;
/**
* 错误响应
*/
private final String ERROR_RESPONSE = "{\"status\":404,\"msg\":\"请求失败\",\"data\":null}";
/**
* 网络错误返回10001
*/
private final String ERROR_NET_WORD = "{\"status\":10001,\"msg\":\"网络异常\",\"data\":null}";
/**
* 数据解析错误
*/
private final String ERROR_JSON_DATA = "{\"status\":10002,\"msg\":\"解析错误\",\"data\":null}";
/**
* 连接超时
*/
private final String ERROR_CONNECT_TIMEOUT = "{\"status\":10003,\"msg\":\"连接超时\",\"data\":null}";
/**
* 请求超时
*/
private final String ERROR_SOCKET_TIMEOUT = "{\"status\":10004,\"msg\":\"请求超时\",\"data\":null}";
public QuietSubscriber(OnNext<T> nextListener) {
this.mNextListener = nextListener;
}
@Override
protected void onStart() {
request(1);
}
/**
* 对错误进行统一处理
*/
@Override
public void onError(Throwable e) {
/*获取状态码非200(出现错误)时的response里的body*/
if (e instanceof HttpException) {
ResponseBody body = ((HttpException) e).response().errorBody();
try {
String json = body.string();
/*判断是否是有效的Json数据*/
if (isJson(json)) {
Response response = new Gson().fromJson(json, Response.class);
if (response != null) {
/*等于请求响应回调*/
if (mNextListener instanceof OnNextOnError) {
((OnNextOnError) mNextListener).onError(response);
}
return;
}
}
formJson(ERROR_RESPONSE);
} catch (IOException ioE) {
ioE.printStackTrace();
}
} else if (e instanceof ConnectException || e instanceof UnknownHostException) {
/*网络错误返回的异常*/
formJson(ERROR_NET_WORD);
} else if (e instanceof JsonSyntaxException) {
/*保证返回的异常为json数据*/
formJson(ERROR_JSON_DATA);
} else if (e instanceof ConnectTimeoutException) {
/*连接超时*/
formJson(ERROR_CONNECT_TIMEOUT);
} else if (e instanceof SocketTimeoutException) {
/*请求超时*/
formJson(ERROR_SOCKET_TIMEOUT);
} else {
/*保证返回的异常为json数据*/
formJson(ERROR_RESPONSE);
}
}
@Override
public void onComplete() {
}
@Override
public void onNext(T t) {
handle(t);
}
/**
* 判断是否是json数据
*/
private boolean isJson(String json) {
try {
new JsonParser().parse(json);
return true;
} catch (JsonParseException e) {
return false;
}
}
private void formJson(String json) {
if (mNextListener instanceof OnNextOnError) {
Response response = new Gson().fromJson(json, Response.class);
((OnNextOnError) mNextListener).onError(response);
}
}
/**
* 这里还需要判断发回的数据是否合法
* 将onNext方法中的返回结果交给网络调用者自己处理
*/
public void handle(T t) {
if (mNextListener == null) {
onError(new Exception("The call nextListener is null"));
return;
}
/*返回的数据result*/
mNextListener.onNext(t);
}
}
有加载提示
/**
* 作者:lpx on 2020/3/20 14:00
* Email : 1966353889@qq.com
* Describe:有加载提示的订阅者,后台加载,开始加载时显示提示框,结束时隐藏提示框
*/
public class ProgressSubscriber<T> extends QuietSubscriber<T> {
/**
* 进度条的实现类
*/
private IFDialog dialogImp;
public ProgressSubscriber(IFDialog dialogImp, OnNext<T> nextListenter) {
super(nextListenter);
this.dialogImp = dialogImp;
}
/**
* 订阅开始时调用
* 显示ProgressDialog
*/
@Override
public void onStart() {
request(1);
dialogImp.showLoading();
}
/**
* 对错误进行统一处理
* 隐藏ProgressDialog
*
* @param e
*/
@Override
public void onError(final Throwable e) {
dialogImp.dismissLoading();
super.onError(e);
}
/**
* 将onNext方法中的返回结果交给Activity或Fragment自己处理
*/
@Override
public void onNext(final T t) {
/*隐藏ProgressDialog*/
dialogImp.dismissLoading();
handle(t);
}
}
请求提示实现Interface
/**
* 作者:lpx on 2020/3/19 14:06
* Email : 1966353889@qq.com
* Describe:网络请求加载提示回调接口
*/
public interface IFDialog {
/**
* 显示加载提示
*/
void showLoading();
/**
* 隐藏加载提示
*/
void dismissLoading();
}
自定义网络请求响应体
这里可以根据项目中接口返回数据的实际情况调整
/**
* 作者:lpx on 2020/3/19 11:23
* Email : 1966353889@qq.com
*/
public class Response<T> implements Serializable {
public Integer status = -1;
public Object msg;
public T data;
public Integer status() {
return status;
}
public String getMsg() {
if (msg == null) {
return "";
} else {
if (msg instanceof String) {
return (String) msg;
} else {
return "";
}
}
}
public Object data() {
return data;
}
}
网络请求回调监听
只包含成功
/**
* 作者:lpx on 2020/3/19 14:15
* Email : 1966353889@qq.com
* Describe:网络请求结果回调接口(只包含成功)
*/
public interface OnNext<T> {
/**
* @param t 网络请求结果成功(响应码为200)时将返回的Json解析
* 后对应的实体类,注:如T的类型为Object,调toString()
* 后json各字段名和对应的的值是不带引号的,如需要看到引号则需调Gson.toJson。
* 如果采用JsonObject则不存在这个问题,注意是JsonObject不是JSONObject。
* */
void onNext(T t);
}
包含成功和失败
/**
* 作者:lpx on 2020/3/19 14:16
* Email : 1966353889@qq.com
* Describe:网络请求结果回调接口(包含成功和失败)
*/
public interface OnNextOnError<T> extends OnNext<T> {
void onError(Response errorResponse);
}
接下来就是标准的retrofit的用法了
新增一个网络请求工具类
配合rxjava订阅网络请求
/**
* 作者:lpx on 2020/3/20 14:00
* Email : 1966353889@qq.com
* update on 2020/3/23 15:06
*/
public class RxUtils {
/**
* 支持回调加载提示的的网络请求
*
* @param dialogImp 加载提示接口
* @param flowable Flowable是为了更好地处理背压问题而新设计的类以弥补Observable的不足,
* 也就是说,Observable不支持背压处理,一旦未及时处理的事件数累积到一定
* 程度就会产生MissingBackpressureException或者OutOfMemoryError。
* @param nextListener 网络请求回调事件监听
*/
public static <T> Disposable rx(IFDialog dialogImp, Flowable<T> flowable, OnNext<T> nextListener) {
return flowable
.onBackpressureDrop() //加上背压策略
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new ProgressSubscriber<>(dialogImp, nextListener));
}
/**
* 不支持回调加载提示的的网络请求
*
* @param flowable Flowable是为了更好地处理背压问题而新设计的类以弥补Observable的不足,
* 也就是说,Observable不支持背压处理,一旦未及时处理的事件数累积到一定
* 程度就会产生MissingBackpressureException或者OutOfMemoryError。
* @param nextListener 网络请求回调事件监听
*/
public static <T> Disposable rx(Flowable<T> flowable, OnNext<T> nextListener) {
return flowable
.onBackpressureDrop() //加上背压策略
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new QuietSubscriber<>(nextListener));
}
/**
* 创建请求体,POST、PUT、PATCH请求都需要设置
*
* @param data 请求体中的数据 ,json格式
* @return
*/
public static RequestBody createRequestBody(String data) {
return RequestBody.create(MediaType.parse("application/json; charset=utf-8"), data);
}
/**
* 创建请求体,POST、PUT、PATCH请求都需要设置
*
* @return
*/
public static RequestBody createRequestBody(Map<String, Object> params) {
String json = GsonTools.toJson(params);
return RxUtils.createRequestBody(json);
}
}
新建网络请求入口基类
对应retrofit的请求api
/**
* 作者:lpx on 2020/3/19 10:55
* Email : 1966353889@qq.com
* Describe:网络请求入口基类,子类实现具体的接口请求服务
* update on 2020/4/17 16:01
*/
public abstract class BaseApi<T> {
/**
* 子类实现,返回对应接口请求服务的class,如xx.class
*/
public abstract Class<T> getHttpServiceClass();
/**
* 网络请求服务接口(框架限制不能extends其他的interface)
* API interfaces must not extend other interfaces.
*/
private T mService;
/**
* 返回HService
*/
public T getService() {
if (mService == null) {
synchronized (BaseApi.class) {
if (mService == null) {
Retrofit retrofit;
/*OkHttp设置*/
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.retryOnConnectionFailure(true)//请求连接失败后重连
.connectTimeout(connectTimeout(), timeUnit())//设置连接超时时间
.readTimeout(readTimeout(), timeUnit())//设置读取超时时间
.writeTimeout(writeTimeout(), timeUnit())//设置写入超时时间
.addInterceptor(new HostInterceptor())//设置host拦截
.addInterceptor(new HeaderInterceptor());//设置header拦截
/*这里的baseUrl的值无任何实际作用,但是retrofit实例一定需要先设置这个值且不为null或“”*/
retrofit = new Retrofit.Builder()
.baseUrl(Constant.baseUrl)
.client(builder.build())
.addConverterFactory(GsonConverterFactory.create())//gson转换工厂
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())//解析rxjava的适配器
.build();
mService = retrofit.create(getHttpServiceClass());
}
}
}
return mService;
}
/**
* 连接超时时间(默认返回NetworkConfig的实现,也可在子类重写)
*/
public long connectTimeout() {
return NetworkConfig.getInstance().getConnectTimeout();
}
/**
* 读取超时时间(默认返回NetworkConfig的实现,也可在子类重写)
*/
public long readTimeout() {
return NetworkConfig.getInstance().getReadTimeout();
}
/**
* 写入超时时间(默认返回NetworkConfig的实现,也可在子类重写)
*/
public long writeTimeout() {
return NetworkConfig.getInstance().getWriteTimeout();
}
/**
* 超时时间对应的时间单位(默认返回NetworkConfig的实现,也可在子类重写)
*/
public TimeUnit timeUnit() {
return NetworkConfig.getInstance().getTimeUnit();
}
}
新建网络请求全局配置NetworkConfig
/**
* 作者:lpx on 2020/4/13 11:42
* Email : 1966353889@qq.com
* Describe:外部设置全局Headers(一般是主工程使用,网络库优先使用设置的全局Headers)
* update on 2020/4/13 13:57
*/
public class NetworkConfig {
private static NetworkConfig mInstance;
private Map<String, String> headers;
/**
* 连接超时时间
*/
private long connectTimeout = 10;
/**
* 读取超时时间
*/
private long readTimeout = 20;
/**
* 写入超时时间
*/
private long writeTimeout = 20;
/**
* 超时时间对应的时间单位
*/
private TimeUnit timeUnit = TimeUnit.SECONDS;
private BaseServer mServer;
private OnResetTokenListener mResetTokenListener;
private NetworkConfig() {
headers = new HashMap<>();
}
/**
* 对外提供的GlobalHeaders实例
*/
public static NetworkConfig getInstance() {
if (mInstance == null) {
synchronized (NetworkConfig.class) {
if (mInstance == null) {
mInstance = new NetworkConfig();
}
}
}
return mInstance;
}
/**
* 设置全局请求头(全部覆盖,一般是主工程调用)
*/
public void headers(Map<String, String> headers) {
this.headers = headers;
}
/**
* 设置全局请求头(单个覆盖,一般是主工程调用)
*/
public void header(String key, String value) {
headers.put(key, value);
}
/**
* 获取全局请求头(一般是主工程调用)
*/
public Map<String, String> getHeaders() {
return headers;
}
/**
* 获取某个请求头
*/
public String getHeader(String key) {
return headers != null ? headers.get(key) : null;
}
/**
* 获取连接超时时间
*/
public long getConnectTimeout() {
return connectTimeout;
}
/**
* 设置连接超时时间
*/
public void setConnectTimeout(long connectTimeout) {
this.connectTimeout = connectTimeout;
}
/**
* 获取读取超时时间
*/
public long getReadTimeout() {
return readTimeout;
}
/**
* 设置读取超时时间
*/
public void setReadTimeout(long readTimeout) {
this.readTimeout = readTimeout;
}
/**
* 获取写入超时时间
*/
public long getWriteTimeout() {
return writeTimeout;
}
/**
* 设置写入超时时间
*/
public void setWriteTimeout(long writeTimeout) {
this.writeTimeout = writeTimeout;
}
/**
* 获取超时时间对应的时间单位
*/
public TimeUnit getTimeUnit() {
return timeUnit;
}
/**
* 设置超时时间对应的时间单位
*/
public void setTimeUnit(TimeUnit timeUnit) {
this.timeUnit = timeUnit;
}
/**
* 获取请求环境
*/
public BaseServer getServer() {
if (mServer == null) {
mServer = new IoServer();
}
return mServer;
}
/**
* 设置请求环境
*/
public void setServer(BaseServer mServer) {
this.mServer = mServer;
}
}
新建网络环境基类
/**
* 作者:lpx on 2020/3/18 17:24
* Email : 1966353889@qq.com
* Describe:常量接口(辅助网络请求)
*/
public interface Constant {
String baseUrl = "https://api.test.com/";
String IO = "io";
String ORG = "org";
String ORI = "ori";
/*不同的接口服务*/
interface Request {
String HOST_TYPE = "host_type";
int CARD = 1;
int CONFIG = 2;
int COUPONS = 3;
int DISPATCH = 4;
int FEED = 5;
int MP = 6;
int IMG = 7;
int ACCOUNT = 8;
int MSG = 9;
int ORDER = 10;
int PAGE = 11;
int PAY = 12;
int REPORT = 13;
int SEARCH = 14;
int TRAFFIC = 15;
int USER = 16;
int DATA = 17;
int ZHIDAO = 18;
}
}
/**
* 作者:lpx on 2020/3/18 17:28
* Email : 1966353889@qq.com
* Describe:网络请求服务配置基类
*/
public abstract class BaseServer {
public String getUrl(int value) {
String url = "";
switch (value) {
case Constant.Request.CARD:
url = card();
break;
case Constant.Request.CONFIG:
url = config();
break;
case Constant.Request.DISPATCH:
url = dispatch();
break;
case Constant.Request.FEED:
url = feed();
break;
case Constant.Request.MP:
url = mp();
break;
case Constant.Request.IMG:
url = img();
break;
case Constant.Request.ACCOUNT:
url = account();
break;
case Constant.Request.MSG:
url = msg();
break;
case Constant.Request.ORDER:
url = order();
break;
case Constant.Request.PAGE:
url = page();
break;
case Constant.Request.PAY:
url = pay();
break;
case Constant.Request.REPORT:
url = report();
break;
case Constant.Request.SEARCH:
url = search();
break;
case Constant.Request.TRAFFIC:
url = traffic();
break;
case Constant.Request.USER:
url = user();
break;
case Constant.Request.DATA:
url = data();
break;
case Constant.Request.ZHIDAO:
url = zhidao();
break;
}
return url;
}
protected abstract String card();
protected abstract String config();
protected abstract String dispatch();
protected abstract String feed();
protected abstract String mp();
protected abstract String img();
protected abstract String account();
protected abstract String msg();
protected abstract String order();
protected abstract String page();
protected abstract String pay();
protected abstract String report();
protected abstract String search();
protected abstract String traffic();
protected abstract String user();
protected abstract String data();
protected abstract String zhidao();
}
实现内网测试环境网络请求服务配置
/**
* 作者:lpx on 2020/3/18 17:31
* Email : 1966353889@qq.com
* Describe:io环境(内网)网络请求服务配置
*/
public final class IoServer extends BaseServer {
@Override
protected String card() {
return "http://card.api.test.io/";
}
@Override
protected String config() {
return "http://config.api.test.io/";
}
@Override
protected String dispatch() {
return "http://dispatch.api.test.io/";
}
@Override
protected String feed() {
return "http://feed.api.test.io/";
}
@Override
protected String mp() {
return "http://mp.test.io/";
}
@Override
protected String img() {
return "http://img.test.io/";
}
@Override
protected String account() {
return "http://account.api.test.io/";
}
@Override
protected String msg() {
return "http://msg.api.test.io/";
}
@Override
protected String order() {
return "http://order.api.test.io/";
}
@Override
protected String page() {
return "http://page.test.io/";
}
@Override
protected String pay() {
return "http://pay.api.test.io/";
}
@Override
protected String report() {
return "http://report.api.test.io/";
}
@Override
protected String search() {
return "http://search.api.test.io/";
}
@Override
protected String traffic() {
return "http://traffic.api.test.io/";
}
@Override
protected String user() {
return "http://user.api.test.io/";
}
@Override
protected String data() {
return "http://data.test.com/";
}
@Override
protected String zhidao() {
return "http://zhidao.api.test.io/";
}
}
外网测试环境OrgServer
和线上环境OriServer
的配置同内网实现方式一样,都是继承BaseServer实现对应的方法。
新建具体的Retrofit接口请求服务(示例)
/**
* 作者:lpx on 2020/3/19 11:25
* Email : 1966353889@qq.com
* Describe:具体的接口请求服务(示例)
* 使用@Field 与 @FieldMap时,出现@Field parameters can only be used with form encoding.需在对应的方法上加上@FormUrlEncoded
*/
public interface ServiceSample {
/**
* 获取用户信息
*/
@Headers(Constant.Request.HOST_TYPE + ":" + Constant.Request.USER)
@GET("profile/")
Flowable<Response<UserInfo>> getUserInfo();
/**
* 退出登录
*/
@Headers(Constant.Request.HOST_TYPE + ":" + Constant.Request.ACCOUNT)
@POST("logout/")
Flowable<Response<JsonObject>> logout(@Body RequestBody requestBody
);
}
新建Retrofit网络请求入口
/**
* 作者:lpx on 2020/4/7 18:51
* Email : 1966353889@qq.com
* Describe: 网络请求入口
* update on 2020/4/20 11:14
*/
public class LoginApi extends BaseApi<LoginService> {
private static LoginApi mInstance;
@Override
public Class<LoginService> getHttpServiceClass() {
return LoginService.class;
}
public static LoginApi getInstance() {
if (mInstance == null) {
synchronized (LoginApi.class) {
if (mInstance == null) {
mInstance = new LoginApi();
}
}
}
return mInstance;
}
}
上边BaseApi提到了connectTimeout、readTimeout、writeTimeout和timeUnit默认在NetworkConfig实现,如需另外实现也可重写方法,如
/**
* 作者:lpx on 2020/4/7 18:51
* Email : 1966353889@qq.com
* Describe: 网络请求入口
* update on 2020/4/20 11:14
*/
public class LoginApi extends BaseApi<LoginService> {
private static LoginApi mInstance;
@Override
public Class<LoginService> getHttpServiceClass() {
return LoginService.class;
}
public static LoginApi getInstance() {
if (mInstance == null) {
synchronized (LoginApi.class) {
if (mInstance == null) {
mInstance = new LoginApi();
}
}
}
return mInstance;
}
/**
* 连接超时时间(默认返回NetworkConfig的实现,也可在子类重写)
*/
public long connectTimeout() {
return 30;
}
/**
* 读取超时时间(默认返回NetworkConfig的实现,也可在子类重写)
*/
public long readTimeout() {
return 30;
}
/**
* 写入超时时间(默认返回NetworkConfig的实现,也可在子类重写)
*/
public long writeTimeout() {
return 30;
}
/**
* 超时时间对应的时间单位(默认返回NetworkConfig的实现,也可在子类重写)
*/
public TimeUnit timeUnit() {
return TimeUnit.SECONDS;
}
}
先来看下我们怎么把对应的网络请求设置在对应的请求环境。这里我们使用Okhttp的Interceptor来实现,我们的ServiceSample中每个请求都设置了表示是什么服务的请求头headers,如@Headers(Constant.Request.HOST_TYPE + “:” + Constant.Request.USER)表示USER服务,Constant.Request.HOST_TYPE作为服务的key标识,我们可在Interceptor中遍历headers拿到key为Constant.Request.HOST_TYPE的header值,就可以知道该请求是走的什么服务了,在通过我们自定义的BaseServer就可以拿到对应的主机请求地址。
自定义HostInterceptor
/**
* 作者:lpx on 2020/4/7 18:51
* Email : 1966353889@qq.com
* Describe: 网络请求拦截器,用于动态修改请求的host
* update on 2020/4/20 11:14
*/
public class HostInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
/*获取request*/
Request request = chain.request();
/*获取request的创建者builder*/
Request.Builder builder = request.newBuilder()/*.removeHeader("Accept-Encoding")*/;
/*从request中获取headers,通过给定的键url_name*/
List<String> headerValues = request.headers(Constant.Request.HOST_TYPE);
if (headerValues != null && headerValues.size() > 0) {
/*如果有这个header,先将配置的header删除,因此header仅用作app和okhttp之间使用*/
builder.removeHeader(Constant.Request.HOST_TYPE);
/*匹配获得新的BaseUrl*/
String headerValue = headerValues.get(0);
HttpUrl newBaseUrl = HttpUrl.parse(getServer().getUrl(Integer.parseInt(headerValue)));
/*从request中获取原有的HttpUrl实例oldHttpUrl*/
HttpUrl oldHttpUrl = request.url();
/*重建新的HttpUrl,修改需要修改的url部分*/
HttpUrl newFullUrl = oldHttpUrl
.newBuilder()
.scheme(newBaseUrl.scheme())
.host(newBaseUrl.host())
.port(newBaseUrl.port())
.build();
/*重建这个request,通过builder.url(newFullUrl).build();*/
/*然后返回一个response至此结束修改*/
return chain.proceed(builder.url(newFullUrl).build());
} else {
return chain.proceed(builder.build());
}
}
/**
* 子类实现,返回对应build环境的BaseServer
*/
private BaseServer getServer() {
return NetworkConfig.getInstance().getServer();
}
}
从HostInterceptor我们发现请求环境是通过getServer()方法获取的,getServer()方法返回NetworkConfig.getInstance().getServer();我们也可以提前通过NetworkConfig.getInstance().setServer(BaseServer baseServer);设置我们的请求环境,如NetworkConfig.getInstance().setServer(new IoServer());将当前请求环境设置为内网请求环境等。
我们新建一个Interceptor用于统一添加网络请求的请求头:
/**
* 作者:lpx on 2020/4/7 18:51
* Email : 1966353889@qq.com
* Describe:全局请求头拦截器
* update on 2020/4/20 11:14
*/
public class HeaderInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request.Builder mBuilder = chain.request().newBuilder().removeHeader("Accept-Encoding");
Map<String, String> mHeadersMap = getHeaders();
if (mHeadersMap != null) {
for (Map.Entry<String, String> entry : mHeadersMap.entrySet()) {
if (!TextUtils.isEmpty(entry.getValue())) {
mBuilder.header(entry.getKey(), entry.getValue());
}
}
}
return chain.proceed(mBuilder.build());
}
/**
* 获取要添加的请求头(通过NetworkConfig获取,具体设置请求头可查看NetworkConfig类)
*/
private Map<String, String> getHeaders() {
return NetworkConfig.getInstance().getHeaders();
}
}
这里我们举例发起一次网络请求
如获取用户信息
只关心成功结果
RxUtils.rx(LoginApi.getInstance().getService().getUserInfo(), new OnNext<Response<UserInfo>>() {
@Override
public void onNext(Response<UserInfo> userInfoResponse) {
/*请求成功*/
/*mUserInfo为用户信息对应实体*/
/*这里的回调参数Response<UserInfo> userInfoResponse对应ServiceSample的getUserInfo()的返回值*/
UserInfo mUserInfo=userInfoResponse.data;
}
});
既关心成功结果也关心失败结果
RxUtils.rx(LoginApi.getInstance().getService().getUserInfo(), new OnNextOnError<Response<UserInfo>>() {
@Override
public void onError(Response response) {
/*请求失败*/
Toast.makeText(context,response.getMsg(),Toast.LENGTH_LONG).show();
}
@Override
public void onNext(Response<UserInfo> userInfoResponse) {
/*请求成功*/
/*mUserInfo为用户信息对应实体*/
/*这里的回调参数Response<UserInfo> userInfoResponse对应ServiceSample的getUserInfo()的返回值*/
UserInfo mUserInfo=userInfoResponse.data;
}
});
只关心成功结果(带加载提示,可用于实现加载loading)
RxUtils.rx(new IFDialog() {
@Override
public void showLoading() {
/*可在这里实现loading效果,如弹出带loading效果的Dialog*/
}
@Override
public void dismissLoading() {
/*可在这里关闭loading效果,如dismiss带loading效果的Dialog*/
}
}, LoginApi.getInstance().getService().getUserInfo(), new OnNext<Response<UserInfo>>() {
@Override
public void onNext(Response<UserInfo> userInfoResponse) {
/*请求成功*/
/*mUserInfo为用户信息对应实体*/
/*这里的回调参数Response<UserInfo> userInfoResponse对应ServiceSample的getUserInfo()的返回值*/
UserInfo mUserInfo=userInfoResponse.data;
}
});
既关心成功结果也关心失败结果
(带加载提示,可用于实现加载loading)`
RxUtils.rx(new IFDialog() {
@Override
public void showLoading() {
/*可在这里实现loading效果,如弹出带loading效果的Dialog*/
}
@Override
public void dismissLoading() {
/*可在这里关闭loading效果,如dismiss带loading效果的Dialog*/
}
}, LoginApi.getInstance().getService().getUserInfo(), new OnNextOnError<Response<UserInfo>>() {
@Override
public void onError(Response response) {
/*请求失败*/
Toast.makeText(context,response.getMsg(),Toast.LENGTH_LONG).show();
}
@Override
public void onNext(Response<UserInfo> userInfoResponse) {
/*请求成功*/
/*mUserInfo为用户信息对应实体*/
/*这里的回调参数Response<UserInfo> userInfoResponse对应ServiceSample的getUserInfo()的返回值*/
UserInfo mUserInfo=userInfoResponse.data;
}
});
组件化
如果我们有组件化的需求,前边的网络请求的相关类可以放在module中,对应的BaseServer根据项目自行更改调整,NetworkConfig自行配置好,每个项目(这里我们举例登录组件)都需要自定义一个LoginApi,LoginService,IoServer,OrgServer,OriServer,在我们需要用到网络请求的项目工程中把这个module依赖进去,或者将module打包成aar文件给需要用到的项目implementation进去,就可以快速拥有网络库的功能了。
结尾
是不是很方便快捷,希望本文可以帮助到您,也希望各位不吝赐教,提出您在使用中的宝贵意见,谢谢。
如果可以的话,也可以扫一扫下方的二维码请作者喝一杯奶茶哈
谢谢您的观看。
有问题可发送至:1966353889@qq.com
欢迎交流,共同进步。