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呢,这样我们就不必谢很多的接口参数了
待续...
以上是关于RxJava的封装和研究的主要内容,如果未能解决你的问题,请参考以下文章
为什么要用Volley中的RequestFuture封装RxJava来用异步请求处理同步请求?
Rxjava +Retrofit 你需要掌握的几个技巧,Retrofit缓存,RxJava封装,统一对有无网络处理,异常处理, 返回结果问题