你知道RxJava也可以实现AsyncTask吗?
使用RxJava实现异步操作(AsyncTask)
常见的异步操作我们可以联想到AsyncTask
或者handler
,其实google创造出的目的也就是为了让代码更加清晰明了,让代码更加简洁.
而Rx系列的出现也就为了实现代码的逻辑清晰,结构简单问题.在gitHub上的介绍是 a library for composing asynchronous and event-based programs using observable sequences for the Java VM"(一个在 Java VM 上使用可观测的序列来组成异步的、基于事件的程序的库)
没错,就是这样,我们可以通过他的操作符,通过他的线程切换,来实现各种Android上遇到的问题.如异步任务,事件总线,数据处理,Retrofit框架等.
提出需求
AsyncTask是异步操作最常见的处理方式,几乎只要涉及到网络请求的,或者耗时操作的,都会使用到AsyncTask
,下面看看一个小需求.
- 给一个接口(查询IP)
http://ip.taobao.com/service/getIpInfo.php- 请求参数是
IP地址: ip=192.168.0.1- 功能实现
请求时弹出进度框,请求完成隐藏进度框,并Toast出获取到的数据(需要将数据封装成bean).
常见的异步操作AsyncTask
下面我们使用AsyncTask
来实现提出的需求.talk is cheap,请看代码.
//点击发出请求
comTitleStartTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
asyncTask();
}
});
具体的AsyncTask
处理如下.
private void asyncTask() {
new AsyncTask<String, Void, IPInfo>() {
@Override
protected IPInfo doInBackground(String... params) {
// 在后台请求接口,并对请求到的json进行校验,解析成json
String resultJsonStr = OkHttpUtil.get(Constants.ipUrl + getParam(params));
IPInfo infos = null;
if (resultJsonStr != null && !"".equals(resultJsonStr)) {
infos = new Gson().fromJson(resultJsonStr, IPInfo.class);
}
return infos;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
// 请求过程耗时操作,弹出Loading的进度框.
if (dialog == null) {
dialog = ProgressDialog.show(MainActivity.this, "Loading...", "正在加载...", true, false);
}
}
@Override
protected void onPostExecute(IPInfo info) {
// 请求完成,关闭进度框,并Toask请求后的结果数据.
if (dialog != null)
CHelper.disimissDialog(dialog);
if (info != null) {
Toast.makeText(MainActivity.this, "AsyncTask:" + info.toString(), Toast.LENGTH_SHORT).show();
}
}
}.execute("192.168.0.1");
}
protected String getParam(String... p) {
return "?ip=" + p[0];
}
下面是AsyncTask的效果.
RxJava封装的异步操作
下面使用到了RxJava的操作符有线程切换subscribeOn
,observeOn
,doOnSubscribe
,doOnCompleted
,doOnError
.
- 封装BaseRxTask,主要是抽取公共方法和封装共性的功能.
如:getBaseDilogView
主要是封装进度框,处理了io和UI线程.
/**
* @Author: Relice
* BaseRX 异步任务基类
*/
public abstract class BaseRxTask<D, P> {
/**
* 参数数组
*/
protected P[] p;
protected Context mContext;
private boolean needDialog = false;
private ProgressDialog dialog;
/**
* 接口不需要传参数 复写此方法
*/
protected BaseRxTask(Context context, boolean needDialog) {
this.mContext = context;
this.needDialog = needDialog;
}
/**
* 接口需要传参数调 复写此方法
*
* @param context 上下文
* @param needDialog 是否显示进度
* @param p 参数数组
*/
@SafeVarargs
protected BaseRxTask(Context context, boolean needDialog, P... p) {
this.mContext = context;
this.needDialog = needDialog;
this.p = p;
}
protected Observable<D> doInBackgroundObserVable() {
return doInBackground();
}
public Observable<D> execute() {
return getBaseDilogView();
}
/**
* 进度View
*
* @return
*/
private Observable<D> getBaseDilogView() {
Observable<D> tObservable = doInBackgroundObserVable();
//subscribeOn(Schedulers.io())事件所产生的线程,也就是subscribe所发生的线程.
return tObservable.subscribeOn(Schedulers.io())
//doOnSubscribe的作用是如它后面有subscribeOn(),那么它将执行
//离它最近的subscribeOn()所指定的线程,也就是下面的 //observeOn(AndroidSchedulers.mainThread())线程.
.doOnSubscribe(new Action0() {
@Override
public void call() {
if (needDialog && mContext != null) {
dialog = ProgressDialog.show(mContext, "Loading...", "正在加载...", true, false);
}
}
// 注意这里添加了doOnCompleted,doOnError两个预处理的操作,
//所以在后面对Observable的订阅就要用subscribe(new Observer),如果使用subscribe(new Action)会报错.
}).doOnCompleted(new Action0() {
@Override
public void call() {
CHelper.disimissDialog(dialog);
}
}).doOnError(new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
CHelper.disimissDialog(dialog);
}
})
//为了让进度框可以在UI线程里执行,影响了上面doOnSubscribe的线程
.observeOn(AndroidSchedulers.mainThread());
}
protected abstract Observable<D> doInBackground();
/**
* 接口没参数空实现即可
*
* @param p 参数数组
*/
protected abstract String getParam(P... p);
/**
* @return BaseUrl
*/
protected abstract String getBaseUrl();
}
实现BaseRxTask
因为在基类对所以的操作都封装好了,所以对BaseRxTask的实现就很简单了,代码中都有注释.public class GetRxIPInfoTask extends BaseRxTask<IPInfo, String> { protected GetRxIPInfoTask(Context context, boolean needDialog) { super(context, needDialog); } public GetRxIPInfoTask(Context context, boolean needDialog, String... p) { super(context, needDialog, p); } @Override public Observable<IPInfo> execute() { return super.execute(); } @Override protected Observable<IPInfo> doInBackground() { return Observable.create(new Observable.OnSubscribe<IPInfo>() { @Override public void call(Subscriber<? super IPInfo> subscriber) { if (!subscriber.isUnsubscribed()) { String resultJsonStr = OkHttpUtil.get(nullToEmpty(getBaseUrl()) + nullToEmpty(getParam(p))); if (resultJsonStr != null && !"".equals(resultJsonStr)) { IPInfo infos = new Gson().fromJson(resultJsonStr, IPInfo.class); subscriber.onNext(infos); subscriber.onCompleted(); } else { subscriber.onCompleted(); } } } }); } private String nullToEmpty(String str) { return (str == null) ? "" : str; } /** * ip * * @param p 参数数组 */ @Override protected String getParam(String... p) { return "?ip=" + p[0]; } /** * @return base url */ @Override protected String getBaseUrl() { return Constants.ipUrl; } }
如何去调用
机智的你们可以看到在基类中的execute()方法封装了 进度框的功能,
public Observable<D> execute() {
return getBaseDilogView();
}
具体调用看下面代码
private void rxAsyncTask() {
new GetRxIPInfoTask(MainActivity.this, true, new String[]{"192.168.0.1"})
.execute()
//提前过滤掉不想要的数据
// .filter(new Func1<IPInfo, Boolean>() {
// @Override
// public Boolean call(IPInfo ipInfo) {
// return ipInfo == null;
// }
// })
.subscribe(new Observer<IPInfo>() {
@Override
public void onCompleted() {
System.out.println("onCompleted");
}
@Override
public void onError(Throwable e) {
System.out.println("Throwable:" + e.getMessage());
}
@Override
public void onNext(IPInfo infos) {
System.out.println("onNext:" + infos.toString());
Toast.makeText(MainActivity.this, "RxAsyncTask:" + infos.toString(), Toast.LENGTH_SHORT).show();
}
});
}
最后我们看看RxAsyncTask的效果.
你知道RxJava也可以实现AsyncTask吗?的更多相关文章
- 【腾讯Bugly干货分享】基于RxJava的一种MVP实现
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57bfef673c1174283d60bac0 Dev Club 是一个交流移动 ...
- Android开发学习之路-Android中使用RxJava
RxJava的核心内容很简单,就是进行异步操作.类似于Handler和AsyncTask的功能,但是在代码结构上不同. RxJava使用了观察者模式和建造者模式中的链式调用(类似于C#的LINQ). ...
- RxJava 学习笔记(一)
最近Android6.0的权限问题,要把之前的APP进行改造,用到了RxPermission框架!之前了解过RXJAVA,但是由于之前项目一直没有使用这个框架,所以也就一直搁置了.正好Rxpermis ...
- 深入浅出RxJava
深入浅出RxJava(一:基础篇) 深入浅出RxJava(二:操作符) 深入浅出RxJava三--响应式的好处 深入浅出RxJava四-在Android中使用响应式编程 RxJava 到底是什么? 一 ...
- 78. Android之 RxJava 详解
转载:http://gank.io/post/560e15be2dca930e00da1083 前言 我从去年开始使用 RxJava ,到现在一年多了.今年加入了 Flipboard 后,看到 Fli ...
- Android中使用反应式编程RxJava
GitHut 地址: https://github.com/ReactiveX/RxAndroid (1)RxJava简介: RxJava 是一个在Java虚拟机上实现的响应式扩展库:提供了基于obs ...
- 关于 RxJava 技术介绍
Awesome-RxJava RxJava resources Blog 给 Android 开发者的 RxJava 详解 -强烈推荐 扔物线的文章 讲解非常详细 NotRxJava懒人专用指南 -这 ...
- 给 Android 开发者的 RxJava 详解
我从去年开始使用 RxJava ,到现在一年多了.今年加入了 Flipboard 后,看到 Flipboard 的 Android 项目也在使用 RxJava ,并且使用的场景越来越多 .而最近这几个 ...
- RxJava简介
RxJava简介 本文为前段时间学习RxJava时留下的历史遗留笔记,仅作纪念,科学的大神教学帖子在这里-> 给 Android 开发者的 RxJava 详解 通过链式调用序列实现基于事件流的异 ...
随机推荐
- [HNOI 2005]狡猾的商人
Description 刁姹接到一个任务,为税务部门调查一位商人的账本,看看账本是不是伪造的.账本上记录了n个月以来的收入情况,其中第i 个月的收入额为Ai(i=1,2,3...n-1,n), .当 ...
- [SCOI2009]围豆豆
Description Input 第一行两个整数N和M,为矩阵的边长. 第二行一个整数D,为豆子的总个数. 第三行包含D个整数V1到VD,分别为每颗豆子的分值. 接着N行有一个N×M的字符矩阵来描述 ...
- 矩阵树Matrix-Tree定理与行列式
简单入门一下矩阵树Matrix-Tree定理.(本篇目不涉及矩阵树相关证明) 一些定义与定理 对于一个无向图 G ,它的生成树个数等于其基尔霍夫Kirchhoff矩阵任何一个N-1阶主子式的行列式的绝 ...
- TopCoder SRM 560 Div 1 - Problem 1000 BoundedOptimization & Codeforces 839 E
传送门:https://284914869.github.io/AEoj/560.html 题目简述: 定义"项"为两个不同变量相乘. 求一个由多个不同"项"相 ...
- 【BZOJ1026】【SCOI2009】windy数
Description windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道,在A和B之间,包括A和B,总共有多少个windy数? In ...
- [POI2000] 最长公共子串
给出几个由小写字母构成的单词,求它们最长的公共子串的长度. 任务 从文件中读入单词 计算最长公共子串的长度 输出结果到文件 输入 文件的第一行是整数 n,1<=n<=5,表示单词的数量.接 ...
- SQL Server 连接 MySQL
1.在SQL SERVER服务器上安装MYSQL ODBC驱动; 驱动下载地址:http://dev.mysql.com/downloads/connector/odbc/ 2.安装好后,在管理工具- ...
- jqGrid移动滑块时冻结首列和第二列例子
js代码如以下代码:在initAllGrid函数colModel1加入属性设置:frozen:true:然后在_initGrid('task_con_grid_div',colModel1)函数里面加 ...
- 笔记14 Hello Spring MVC
搭建一个SpringMVC所需要的包: 1.创建MySpringMVC项目,使用dynamic web project的方式. 2.导入jar包,放到/WebContent(WebRoot)/WEB- ...
- sprintf()、fprintf()、fscanf()的用法
sprintf函数的用法1.该函数包含在stdio.h的头文件中. 2.sprintf和平时我们常用的printf函数的功能很相似.sprintf函数打印到字符串中,而printf函数打印输出到屏幕上 ...