RxJava的封装和研究

对于RxJava,现在有大量的博客来讲解,但是学会了RxJava不代表它好用,得适当的封装一下,达到我们的开发要求。

RxJava的常规用法:

API.Retrofit().getListInfo(params)
	.subscribeOn(Schedulers.io())
	.observeOn(AndroidSchedulers.mainThread())
	.subscribe(new Observer<ResultBean>() {
		@Override
		public void onCompleted() {

		}

		@Override
		public void onError(Throwable e) {

		}

		@Override
		public void onNext(ResultBean resultBean) {

		}
});

一、Schedulers线程调度器的研究

线程调度器是用来制定事件线程的,但是在用的过程中还是有诸多不懂,来研究一下,先写一个方法:

1、Observable调度器线程指定


打印


可以看到第二次指定的线程没有起作用,所以需要注意的是:如果在Observable链中调用了多个subscribeOn方法,无论调用点在哪里,Observable链都是以第一个subscribeOn指定的调度器为准。

2、observeOn调度器线程指定


打印


这个打印非常明显,observeOn调度器是用来指定下面的事件发生的线程,也就是说,调用这句代码之后,下面的事件就会被指定发生在哪一个线程,如果中途想切换线程,你可以用observeOn再次指定你想要的线程

这是两个简单的例子,总结来说

  • subscribeOn中途不可以切换线程,一旦指定,不可变
  • observeOn专注于线程切换,中途随时随地切换线程,这也是RxJava的魅力所在。
  • 默认情况下,操作链使用的线程是调用subscribe()的线程
  • Schedulers提供了多个调度器,可以并行运行多个Observable

二、对Observer的研究


这里我们创建的是一个Observer,但是我一般不喜欢用它,我更喜欢用Observer扩展类Subscriber 

API.Retrofit().getListInfo(params)
	.subscribeOn(Schedulers.io())
	.observeOn(AndroidSchedulers.mainThread())
	.subscribe(new Subscriber<ResultBean>() {
		@Override
		public void onStart() {
			super.onStart();
		}

		@Override
		public void onCompleted() {

		}

		@Override
		public void onError(Throwable e) {

		}

		@Override
		public void onNext(ResultBean resultBean) {

		}
});

这个扩展类中多了一个onStart()方法,这个方法对我们是不是有帮助呢?

我们是不是可以在这个方法来设置一些准备工作的事情呢?比如:Loading进度条和网络判断


但是我记得官网有一段文字是这样写的:

onStart(): 这是 Subscriber 增加的方法。它会在 subscribe 刚开始,而事件还未发送之前被调用,可以用于做一些准备工作,例如数据的清零或重置。这是一个可选方法,默认情况下它的实现为空。需要注意的是,如果对准备工作的线程有要求(例如弹出一个显示进度的对话框,这必须在主线程执行), onStart() 就不适用了,因为它总是在 subscribe 所发生的线程被调用,而不能指定线程。要在指定的线程来做准备工作,可以使用 doOnSubscribe() 方法


看来官网不建议我们使用这个方法,那么难道说这个方法就没用了吗?我不这么认为

代码中的observeOn(AndroidSchedulers.mainThread())这句话指定了我们Subscriber发生在UI线程,到底这几个方法真的是运行在UI线程中吗?我们打印一下



打印结果说明这几个方法确实是运行在UI线程的,也就是说我们再用RxAndroid网络请求之前的准备工作如果是运行在UI线程的,这个方法就给我们提供了方便,如果准备工作必须是运行在io等线程的,我们就听官网的话,用doOnSubscribe()这个方法吧。

对于没有特殊的需求的网络请求,我们完全可以用onStart方法的,比如显示和隐藏进度条和网络判断,看代码:

API.Retrofit().getListInfo(params)
	.subscribeOn(Schedulers.io())
	.observeOn(AndroidSchedulers.mainThread())
	.subscribe(new Subscriber<ResultBean>() {
		@Override
		public void onStart() {
			super.onStart();
			//显示Loading进度条
		}

		@Override
		public void onCompleted() {
			//隐藏Loading进度条
		}

		@Override
		public void onError(Throwable e) {
			//隐藏Loading进度条
		}

		@Override
		public void onNext(ResultBean resultBean) {
			//更新UI
		}
});

每次都这样写,太繁琐了吧,我们稍微进行转化封装一下还是可以的

比如我们要的效果是这样的:

MainActivity代码:

API.Retrofit().getListInfo(params)
	.subscribeOn(Schedulers.io())
	.observeOn(AndroidSchedulers.mainThread())
	.subscribe(new BaseSubscriber<ResultBean>(MainActivity.this) {
		@Override
		public void onNext(ResultBean resultBean) {
			Toast.makeText(MainActivity.this,resultBean.getStatusMessage(),Toast.LENGTH_SHORT).show();
		}
});

无关的方法我们统一管理,只在activity中展示需要更新UI的方法,我们可以写一个继承自Subscriber的类BaseSubscriber

BaseSubscriber代码:

/**
 * Subscriber的封装
 *
 * Created by Anonymous on 2016/11/22.
 */

public abstract class BaseSubscriber<T> extends Subscriber<T> {
    private Context mContext;
    private SweetAlertDialog mDialog;

    public BaseSubscriber(Context mContext) {
        this.mContext = mContext;
        mDialog = LoadingDialog.newBuilder(mContext).Builder();
    }

    /**
     * 显示进度条
     */
    @Override
    public void onStart() {
        if (!AppUtil.isNetworkConnected(mContext)){
            Toast.makeText(mContext,"亲,你断网了啊!",Toast.LENGTH_SHORT).show();
            // 一定要调用这个方法才会生效
            onCompleted();
            return;
        }
        mDialog.show();
    }

    /**
     * 关闭进度条
     */
    @Override
    public void onCompleted() {
        mDialog.dismiss();
    }

    /**
     * 网络请求发生错误的处理
     *
     * @param e
     */
    @Override
    public void onError(Throwable e) {
        e.printStackTrace();
        mDialog.dismiss();
        if (AppUtil.isNetworkConnected(mContext)){
            Toast.makeText(mContext,"服务器连接失败!",Toast.LENGTH_SHORT).show();
        }

    }

    /**
     * onNext是对外实现的方法,所以一定是抽象类
     *
     * @param t
     */
    @Override
    public abstract void onNext(T t);
}



这样就可以进行统一管理了,看效果:



效果还算满意,其他的代码如下

Loading进度条代码:

/**
 * Loading进度条
 * Created by Anonymous on 2016/11/22.
 */

public class LoadingDialog {
    private SweetAlertDialog mDialog;
    private static LoadingDialog mLoadingDialog;

    /**
     * 一、私有化构造参数
     * 二、实例化LoadingDialog
     *
     * @param mContext
     */
    private LoadingDialog(Context mContext){
        if (mDialog==null){
            mDialog = new SweetAlertDialog(mContext, SweetAlertDialog.PROGRESS_TYPE);
            mDialog.getProgressHelper().setBarColor(Color.parseColor("#A5DC86"));
            mDialog.setTitleText("Loading");
            mDialog.setCancelable(false);
        }
    }

    /**
     * 创建实例
     *
     * @param mContext
     * @return
     */
    public static LoadingDialog newBuilder(Context mContext){
        if (mLoadingDialog==null){
            mLoadingDialog = new LoadingDialog(mContext);
        }
        return mLoadingDialog;
    }

    /**
     * 暴露方法,返回实例
     *
     * @return
     */
    public SweetAlertDialog Builder(){
        return mDialog;
    }

}


这里贴出两个类,其他的代码可以去我们另一篇文章去copy


二、对APIService接口的研究

上面我们是对一个简单的网络请求准备工作的一个总结,但是还有一个问题,对于没有用过retrofit的项目来说,转retrofit的网络框架需要更改很多的接口(几乎全改),用Retrofit的朋友都知道,一般来说,每一个网络请求我们你都需要定义一个API接口,这样也没错,最起码逻辑和代码都比较清晰,但是能不能写一个通用的APIService呢,这样我们就不必谢很多的接口参数了

待续...


Retrofit的详解与使用(多文件上传)



  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Anonymous-OS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值