RxJava的封装和研究

Posted Anonymous-OS

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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的详解与使用(多文件上传)



以上是关于RxJava的封装和研究的主要内容,如果未能解决你的问题,请参考以下文章

为什么要用Volley中的RequestFuture封装RxJava来用异步请求处理同步请求?

RxJava 笔记

Rxjava,改造和多次调用

RxJava 与 Retrofit 结合的最佳实践

是什么让我们阅读RxJava源码如此艰难?

Rxjava +Retrofit 你需要掌握的几个技巧,Retrofit缓存,RxJava封装,统一对有无网络处理,异常处理, 返回结果问题