蛙笑网络请求优化方案
优化目的
解耦网络请求,解决嵌套地狱,减少内存泄漏
方案对比
- 原始请求方式:
HttpMethods.getInstance().getJsonData(new NoProgressSubscriber(
new SubscriberOnNextListener<RespListBean<GiftItemBean>>() {
@Override
public void onNext(RespListBean<GiftItemBean> o) {
if (null != o) {
if (0 == o.status) {
if (null != o.table) {
if (null != o.table.row && o.table.row.size() > 0) {
giftItemBeanList = new ArrayList<GiftItemBean>();
for (int i = 0; i < o.table.row.size(); i++) {
giftItemBeanList.add(o.table.row.get(i));
}
selectExchangeAdp.getDate(giftItemBeanList);
}
} else {
ToastUtils.getInstance().ShowToast(context, "没有查询到兑换商品");
}
} else {
ToastUtils.getInstance().ShowToast(context, o.msg);
}
} else {
ToastUtils.getInstance().ShowToast(context, "无法连到服务器。");
}
}
}, new TypeToken<RespListBean<GiftItemBean>>() {
}.getType()), getGiftByIntegralExchangeBean);
-
改造完成的请求方式
HttpUtils .createApi(waxiaoApi.class) .getBanner() .compose(Transformer.<BaseData<List<BannerBean>>>switchSchedulers(loading_dialog)) .subscribe(new DataObserver<List<BannerBean>>() { @Override protected boolean isHideToast() { return false; } //tag下的一组或一个请求,用来处理一个页面的所以请求或者某个请求 //设置一个tag就行就可以取消当前页面所有请求或者某个请求了 @Override protected String setTag() { return "tag1"; } @Override protected void onError(String errorMsg) { } @Override protected void onSuccess(RespListBean<GiftItemBean> o) { if ( o.table.row.size() > 0) { giftItemBeanList = new ArrayList<GiftItemBean>(); for (int i = 0; i < o.table.row.size(); i++) { giftItemBeanList.add(o.table.row.get(i)); } selectExchangeAdp.getDate(giftItemBeanList); } } });
方案优势:
-
清晰的结构:
createApi(WanAndroidApi.class)不同的模块使用不同的service
设置tag 取消网络请求,减少崩溃和内存泄漏
loading_dialog
可以继承ILoadingView 接口化处理 让进度条不止能使用dialog
方案的改造成本
- rxjava1.x->rxjava2.x,涉及到api 的更改
- 整理之前的网络请求,换成新的方式
方案的改造细节
createApi
public <A> A createApi(String baseUrlKey, String baseUrlValue, Class<A> apiClass) {
Retrofit retrofit = new RetrofitBuilder()
.setBaseUrl(baseUrlValue)
.setCallAdapterFactory(callAdapterFactory)
.setConverterFactory(converterFactory)
.setOkHttpClient(okHttpClient)
.build();
api = retrofit.create(apiClass);
apiServiceCache.put(key, api);
return api;
}
DataObserver
public abstract class DataObserver<T> extends BaseObserver<RespListBean<T>> {
/**
* 失败回调
*
* @param errorMsg 错误信息
*/
protected abstract void onError(String errorMsg);
/**
* 成功回调
*
* @param data 结果
*/
protected abstract void onSuccess(T data);
@Override
public void doOnSubscribe(Disposable d) {
}
@Override
public void doOnError(String errorMsg) {
if (!isHideToast() && !TextUtils.isEmpty(errorMsg)) {
ToastUtils.showToast(errorMsg);
}
onError(errorMsg);
}
@Override
public void doOnNext(RespListBean<T> data) {
//可以根据需求对code统一处理
// switch (data.getCode()) {
// case 0:
// onSuccess(data.getData());
// break;
// case ..:
// onError(data.getMsg());
// break;
//
// }
//统一做异常处理
if(data==null){
onError(" 无法连到服务器.");
return;
}
onSuccess(data.getData());
}
@Override
public void doOnCompleted() {
}
}
BaseObserver
public abstract class BaseObserver<T> implements Observer<T>, ISubscriber<T> {
/**
* 是否隐藏toast
*
* @return
*/
protected boolean isHideToast() {
return false;
}
/**
* 标记网络请求的tag
* tag下的一组或一个请求,用来处理一个页面的所以请求或者某个请求
* 设置一个tag就行就可以取消当前页面所有请求或者某个请求了
* @return string
*/
protected String setTag(){
return null;
}
@Override
public void onSubscribe(@NonNull Disposable d) {
RxHttpManager.get().add(setTag(), d);
doOnSubscribe(d);
}
@Override
public void onNext(@NonNull T t) {
doOnNext(t);
}
@Override
public void onError(@NonNull Throwable e) {
String error = ApiException.handleException(e).getMessage();
setError(error);
}
@Override
public void onComplete() {
doOnCompleted();
}
private void setError(String errorMsg) {
doOnError(errorMsg);
}
}
Log细节优化:
public class RxHttpLogger implements HttpLoggingInterceptor.Logger {
private StringBuffer mMessage = new StringBuffer();
@Override
public void log(String message) {
// 请求或者响应开始
if (message.startsWith("--> POST")) {
mMessage.setLength(0);
mMessage.append(" ");
mMessage.append("\r\n");
}
if (message.startsWith("--> GET")) {
mMessage.setLength(0);
mMessage.append(" ");
mMessage.append("\r\n");
}
// 以{}或者[]形式的说明是响应结果的json数据,需要进行格式化
if ((message.startsWith("{") && message.endsWith("}"))
|| (message.startsWith("[") && message.endsWith("]"))) {
message = JsonUtil.formatJson(message);
}
mMessage.append(message.concat("\n"));
// 请求或者响应结束,打印整条日志
if (message.startsWith("<-- END HTTP")) {
Log.e("RxHttpUtils", mMessage.toString());
}
}
}
线程切换辅助
public class Transformer {
/**
* 无参数
*
* @param <T> 泛型
* @return 返回Observable
*/
public static <T> ObservableTransformer<T, T> switchSchedulers() {
return switchSchedulers(null);
}
/**
* 带参数 显示loading对话框
*
* @param loadingView loading
* @param <T> 泛型
* @return 返回Observable
*/
public static <T> ObservableTransformer<T, T> switchSchedulers(final ILoadingView loadingView) {
return new ObservableTransformer<T, T>() {
@Override
public ObservableSource<T> apply(@NonNull Observable<T> upstream) {
return upstream
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.doOnSubscribe(new Consumer<Disposable>() {
@Override
public void accept(@NonNull Disposable disposable) throws Exception {
if (loadingView != null) {
loadingView.showLoadingView();
}
}
})
.subscribeOn(AndroidSchedulers.mainThread())
.observeOn(AndroidSchedulers.mainThread())
.doFinally(new Action() {
@Override
public void run() throws Exception {
if (loadingView != null) {
loadingView.hideLoadingView();
}
}
});
}
};
}
}
Api service 请求方式
@POST("posapi/json")
Observable<RespListBean<ListBean>> getItemData(ReqJsonBean bean)
拼装请求bean
val requestJsonBean = ApiHelper.parseRequestBean(XXXRequestbean,funcName)
parseRequestBean核心代码
Gson gson = new GsonBuilder()
.setPrettyPrinting()
.disableHtmlEscaping()
.create();
ReqJsonBean.RequestEntity requestEntity = new ReqJsonBean.RequestEntity();
requestEntity.setRequest(xxxRequest);
ReqJsonBean jsonBean = new ReqJsonBean();
jsonBean.setRequestJson(gson.toJson(requestEntity).replaceAll("\\\\", ""));