Retrofit的设计模式 -- 静态代理模式

今天用代理模式完美解决公司项目的bug.

BUG代码

用RxJava封装的网络请求统一处理方案

public abstract class RxSubUtils extends Subscriber {
    private CompositeSubscription mCompositeSubscription; 
    private Context mContext;    
    private String msg;   
 
    public RxSubUtils(){}    
    public RxSubUtils(CompositeSubscription mCompositeSubscription) {
        this.mCompositeSubscription = mCompositeSubscription;
    }
    /**
     * @param context context
     * @param msg     dialog message
     */
    public RxSubUtils(CompositeSubscription mCompositeSubscription, Context context, String msg) {
        this.mCompositeSubscription = mCompositeSubscription;
        this.mContext = context;
        this.msg = msg;
    }
    /**
     * @param context context
     */
    public RxSubUtils(CompositeSubscription mCompositeSubscription, Context context) {
        this(mCompositeSubscription, context, "请稍后...");
    }
    /**
     * 这个一定要有 Presenter的逻辑在这里处理
     * @param t
     */
    @Override
    public void onNext(T t) {
        _onNext(t);
    }
    @Override
    public void onError(Throwable e) {
        e.printStackTrace();
        LoadingDialogManager.getLoadingDialog().hideDialog();
        if (!NetWorkUtils.isNetworkAvailable()) {
            ToastUtil.show(R.string.net_error);
        } else if (e instanceof RxUtils.ServerException) {//
            String s = ((RxUtils.ServerException)e).getMsg();//
            //token 过期了
            //if(TextUtils.equals(s, RxUtils.TOKEN_OVER_TIME) && mContext != null){
//                Utils.startLoginActivity(mContext);
//            }
//            ToastUtil.show(s);
        } else {
            ToastUtil.show(R.string.error);
        }
        _onError();
    }
    @Override
    public void onCompleted() {
        if (mCompositeSubscription != null)
            mCompositeSubscription.remove(this);
        LoadingDialogManager.getLoadingDialog().hideDialog();
    }
    @Override
    public void onStart() {
        super.onStart();
        if (mContext != null) {
            LoadingDialogManager.getLoadingDialog().showDialog(mContext);
        }
    }
    protected abstract void _onNext(T t);
    /**
     * 错误处理,需要的话重写这个方法
     */
    protected void _onError(){
    }
}

1.统一处理网络请求到的数据
2.可以选择是否添加LoadingDialog
3.可以统一处理特殊情况,如用户信息过期等
使用方法:

public void getDataList(){
    mCompositeSubscription.add(model.getDataList()
            .subscribe(new RxSubUtils>(mCompositeSubscription) {
                @Override
                protected void _onNext(List videoBeen) {
                    getView().getVideoList(videoBeen);
                }
                @Override
                protected void _onError() {
                    getView().onFail();
                }
            }));
}

以上封装只是部分代码,主要不是说明这个问题,APP跑起来,切换各种网络,2G,3G,wifi但访问不到后台数据,wifi能正常访问等操作,就会出现下面bug。
Stack trace is opaque for IllegalStateException: Exception thrown on Scheduler.Worker thread. Add onError handling.
看到最后说到解决方法两种:

  1. 一种是上面的RxSubUtils改为继承SafeSubscriber
  2. 一种是在使用的时候加上Throwable的处理

那么问题来了,第二种方法中上面的使用方法有成百上千个,真是不能手工一个一个改,会死人的,所以就只能用第一种方法,但是第一种方法中继承SafeSubscriber,构造函数就要改变,使用的时候还是每一个地方都要改,还是会死人

-----------------------------------------分割线-----------------------------------------

解决方案:

建立RxSafeSubUtils类继承SafeSubscriber,设置为被代理类,原来的RxSubUtils设置为代理类,改为如下


public class RxSafeSubUtils extends SafeSubscriber {

    private CompositeSubscription mCompositeSubscription;
    private Context mContext;
    private IOSDialog dialog;
    private Subscription subscription;

    public RxSafeSubUtils(Subscriber actual) {
        super(actual);
        subscription = actual;
    }

    public RxSafeSubUtils(Subscriber actual, CompositeSubscription compositeSubscription) {
        super(actual);
        this.mCompositeSubscription = compositeSubscription;
        subscription = actual;
    }

    public RxSafeSubUtils(Subscriber actual, CompositeSubscription compositeSubscription, Context context) {
        this(actual, compositeSubscription);
        this.mContext = context;
        subscription = actual;
    }


    /**
     * 这个一定要有 Presenter的逻辑在这里处理
     * @param t
     */
    @Override
    public void onNext(T t) {
        ((RxSubUtils)subscription).onNext(t);
    }

    @Override
    public void onError(Throwable e) {
        e.printStackTrace();
        if (!NetWorkUtils.isNetworkAvailable()) {
            ToastUtil.show(R.string.net_error);
        } else if (e instanceof RxUtils.ServerException) {
            String s = ((RxUtils.ServerException)e).getMsg();
            //token 过期了
            if(TextUtils.equals(s, RxUtils.TOKEN_OVER_TIME) && mContext != null){
                Utils.startLoginActivity(mContext);
            }
            ToastUtil.show(s);
        } else {
            ToastUtil.show(R.string.error);
        }

        if (dialog!= null){
            dialog.dismiss();
            dialog = null;
        }
        ((RxSubUtils)subscription)._onError();
    }

    @Override
    public void onCompleted() {
        if (mCompositeSubscription != null)
            mCompositeSubscription.remove(this);

        if (dialog != null) {
            dialog.dismiss();
            dialog = null;
        }
    }

    @Override
    public void onStart() {
        super.onStart();
        if (mContext != null && dialog == null) {
            dialog = new IOSDialog(mContext).builder()
                    .setLoadingView(R.color.colorPrimary);
            dialog.show();
        }
    }
}

public abstract class RxSubUtils extends Subscriber {
    private RxSafeSubUtils rxSafeSubUtils;

    public RxSubUtils() {
        rxSafeSubUtils = new RxSafeSubUtils(this);
    }

    public RxSubUtils(CompositeSubscription mCompositeSubscription) {
        rxSafeSubUtils = new RxSafeSubUtils(this, mCompositeSubscription);
    }

    /**
     * @param context context
     */
    public RxSubUtils(CompositeSubscription mCompositeSubscription, Context context) {
        rxSafeSubUtils = new RxSafeSubUtils(this, mCompositeSubscription, context);
    }

    /**
     * 这个一定要有 Presenter的逻辑在这里处理
     * @param t
     */
    public void onNext(T t) {
        _onNext(t);
    }

    @Override
    public void onError(Throwable e) {
        _onError();
    }

    @Override
    public void onCompleted() {
        rxSafeSubUtils.onCompleted();
    }

    @Override
    public void onStart() {
        rxSafeSubUtils.onStart();
    }

    protected abstract void _onNext(T t);

    /**
     * 错误处理,需要的话重写这个方法
     */
    protected void _onError(){

    }

}


这样用的时候, 代码什么都不改,完美解决!
PS:最好的方法还是在开始的时候就想到封装RxSafeSubUtils,不用任何代理!

你可能感兴趣的:(Retrofit的设计模式 -- 静态代理模式)