使用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,下面看看一个小需求.

  1. 给一个接口(查询IP)
    http://ip.taobao.com/service/getIpInfo.php
  2. 请求参数是
    IP地址: ip=192.168.0.1
  3. 功能实现
    请求时弹出进度框,请求完成隐藏进度框,并Toast出获取到的数据(需要将数据封装成bean).

常见的异步操作AsyncTask

下面我们使用AsyncTask来实现提出的需求.talk is cheap,请看代码.

//点击发出请求
comTitleStartTv.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {asyncTask();}});

具体的AsyncTask处理如下.

private void asyncTask() {new AsyncTask<String, Void, IPInfo>() {@Overrideprotected IPInfo doInBackground(String... params) {// 在后台请求接口,并对请求到的json进行校验,解析成jsonString resultJsonStr = OkHttpUtil.get(Constants.ipUrl + getParam(params));IPInfo infos = null;if (resultJsonStr != null && !"".equals(resultJsonStr)) {infos = new Gson().fromJson(resultJsonStr, IPInfo.class);}return infos;}@Overrideprotected void onPreExecute() {super.onPreExecute();// 请求过程耗时操作,弹出Loading的进度框.if (dialog == null) {dialog = ProgressDialog.show(MainActivity.this, "Loading...", "正在加载...", true, false);}}@Overrideprotected 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 参数数组*/@SafeVarargsprotected 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() {@Overridepublic 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() {@Overridepublic void call() {CHelper.disimissDialog(dialog);}}).doOnError(new Action1<Throwable>() {@Overridepublic 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>() {@Overridepublic 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>() {@Overridepublic void onCompleted() {System.out.println("onCompleted");}@Overridepublic void onError(Throwable e) {System.out.println("Throwable:" + e.getMessage());}@Overridepublic void onNext(IPInfo infos) {System.out.println("onNext:" + infos.toString());Toast.makeText(MainActivity.this, "RxAsyncTask:" + infos.toString(), Toast.LENGTH_SHORT).show();}});}

最后我们看看RxAsyncTask的效果.

你知道RxJava也可以实现AsyncTask吗?相关推荐

  1. Android开发,你所不知道的Android原生开发的现状

    此外还有许多针对Android的非关系型的数据库,例如Realm,Parse,Firebase,ObjectBox等(其中有些仍在使用SQLite).如果我没记错的话,它们中的大多数(甚至全部)都具有 ...

  2. 敢问路在何方?国外安卓大神对Android原生开发现状剖析

    点击上方"终端研发部",选择"星标" 回复"资源",领取全网最火的Java核心知识总结~ 前言 原文地址:The State of Nati ...

  3. 浅谈RxJava与2.0的新特性

    简介 说起 RxJava ,相信诸多 Android 开发者都不会陌生.作为一个知名的响应式编程库,从前年开始逐渐变得火热,从小众到被众多 Android 开发者们广泛引入与流传,其在 GitHub ...

  4. Android Retrofit使用教程(三):Retrofit与RxJava初相逢

    上一篇文章讲述了Retrofit的基本使用,包括GET,POST等请求.今天的文章中Retrofit要与RxJava配合使用. 了解RxJava RxJava有种种好处,我不在这里一一讲述.这里我只给 ...

  5. RxJava的初步认识

    希望,记录:RxJava的组成与流程   第一次接触RxJava,它把数据生成与数据使用相分离模型 说明: Observable是数据生成器,数据可以通过各种变换(transform)来整理成需要的格 ...

  6. rxjava获取异步请求的结果_我为什么不再推荐用 RxJava

    点击"开发者技术前线",选择"星标?" 13:21 在看|星标|留言,  真爱 作者: W_BinaryTreehttps://juejin.im/post/5 ...

  7. android ------- 开发者的 RxJava 详解

    在正文开始之前的最后,放上 GitHub 链接和引入依赖的 gradle 代码: Github:  https://github.com/ReactiveX/RxJava  https://githu ...

  8. 深入浅出RxJava(三:响应式的好处)

    在第一篇中,我介绍了RxJava的基础知识.第二篇中,我向你展示了操作符的强大.但是你可能仍然没被说服.这篇里面,我讲向你展示RxJava的其他的一些好处,相信这篇足够让你去使用Rxjava. 错误处 ...

  9. android RxJava(RxAndroid)的简单使用

    今天,简单讲讲android里如何使用RxJava(RxAndroid). Android框架系列: 一.android EventBus的简单使用 二.android Glide简单使用 三.and ...

最新文章

  1. 域名解析可以带端口吗_带互感器的三相电表接线,S2可以不接地吗?ABC相序可以错吗?...
  2. erlang精要(30)-卫语句
  3. 全选按钮的使用。winfrom程序中,对全选按钮的理解,欢迎拍砖!
  4. Confluence 6 考虑使用自定义 CSS
  5. 通过制作数字桌面游戏和Web应用程序学习JavaScript
  6. 一步一步学Remoting系列文章
  7. 在CentOS上安装NodeJS_v14.x
  8. 【报告分享】巨量引擎2019娱乐算数白皮书.pdf(附下载链接)
  9. 正态分布下含绝对值的期望求解 -- 待验证
  10. 数据库管理工具 Navicat使用教程:导航窗格提示和技巧 - 管理连接
  11. angular-devextreme treeview 学习笔记
  12. 11月全国程序员平均工资最新出炉,网友:我丢了同行的脸
  13. Druid监控页面配置与使用
  14. SRM采购框架协议阶梯计价方法
  15. 接口测试 Pytest断言处理_告警断言
  16. Oracle触发器(当A表新增/修改/删除时,同步数据到B表)
  17. 无人驾驶能解决什么问题?
  18. 三分钟了解如何准备简历面试
  19. Chrome浏览器查看、找回保存的网站账户密码
  20. python处理日值气象数据

热门文章

  1. 2093321-19-6,PSMA-1007PSMA1007特异性膜抗原(PSMA)抑制剂
  2. ubuntu 环境搭建问题归纳
  3. Keil5添加STM32芯片包
  4. 重磅:CMMI DEV V2.0发布!
  5. 服务器系统壁纸,云服务器壁纸
  6. 计算机网络实验——路由器基本配置
  7. LI雨骤Moku:Go M1初步体验
  8. 拂晓时分的伤感爱情独特日志发布:其实,我们不需要为爱找借口
  9. 填数字游戏ABCD*E=DCBA
  10. fama matlab源码_Matlab:计算Fama Macbeth方法的HAC(Newey West)标准误差