使用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() {
            @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吗?的更多相关文章

  1. 【腾讯Bugly干货分享】基于RxJava的一种MVP实现

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57bfef673c1174283d60bac0 Dev Club 是一个交流移动 ...

  2. Android开发学习之路-Android中使用RxJava

    RxJava的核心内容很简单,就是进行异步操作.类似于Handler和AsyncTask的功能,但是在代码结构上不同. RxJava使用了观察者模式和建造者模式中的链式调用(类似于C#的LINQ). ...

  3. RxJava 学习笔记(一)

    最近Android6.0的权限问题,要把之前的APP进行改造,用到了RxPermission框架!之前了解过RXJAVA,但是由于之前项目一直没有使用这个框架,所以也就一直搁置了.正好Rxpermis ...

  4. 深入浅出RxJava

    深入浅出RxJava(一:基础篇) 深入浅出RxJava(二:操作符) 深入浅出RxJava三--响应式的好处 深入浅出RxJava四-在Android中使用响应式编程 RxJava 到底是什么? 一 ...

  5. 78. Android之 RxJava 详解

    转载:http://gank.io/post/560e15be2dca930e00da1083 前言 我从去年开始使用 RxJava ,到现在一年多了.今年加入了 Flipboard 后,看到 Fli ...

  6. Android中使用反应式编程RxJava

    GitHut 地址: https://github.com/ReactiveX/RxAndroid (1)RxJava简介: RxJava 是一个在Java虚拟机上实现的响应式扩展库:提供了基于obs ...

  7. 关于 RxJava 技术介绍

    Awesome-RxJava RxJava resources Blog 给 Android 开发者的 RxJava 详解 -强烈推荐 扔物线的文章 讲解非常详细 NotRxJava懒人专用指南 -这 ...

  8. 给 Android 开发者的 RxJava 详解

    我从去年开始使用 RxJava ,到现在一年多了.今年加入了 Flipboard 后,看到 Flipboard 的 Android 项目也在使用 RxJava ,并且使用的场景越来越多 .而最近这几个 ...

  9. RxJava简介

    RxJava简介 本文为前段时间学习RxJava时留下的历史遗留笔记,仅作纪念,科学的大神教学帖子在这里-> 给 Android 开发者的 RxJava 详解 通过链式调用序列实现基于事件流的异 ...

随机推荐

  1. codefroces 946F Fibonacci String Subsequences

    Description定义$F(x)$为$F(x−1)$与$F(x−2)$的连接(其中$F(0)="0"$,$F(1)="1"$)给出一个长度为$n$的$01$ ...

  2. [HNOI2014]江南乐

    Description 小A是一个名副其实的狂热的回合制游戏玩家.在获得了许多回合制游戏的世界级奖项之后,小A有一天突然想起了他小时候在江南玩过的一个回合制游戏.    游戏的规则是这样的,首先给定一 ...

  3. bzoj 5289: [Hnoi2018]排列

    Description Solution 首先注意到实际上约束关系构成了一棵树 考虑这个排列 \(p\),编号为 \(a[i]\) 的出现了,\(i\) 才可以出现 那么如果连边 \((a[i],i) ...

  4. [Noi2013]书法家

    来自FallDream的博客,未经允许,请勿转载,谢谢. 小E同学非常喜欢书法,他听说NOI2013已经开始了,想题一幅“NOI”的字送给大家. 小E有一张非常神奇的纸,纸可以用一个n 行m 列的二维 ...

  5. URLconnection

    URLconnection 开发中最常用的两种网络请求: 1.标准Java接口(java.NET) --HttpURLConnection,可以实现简单的基于URL请求.响应功能:  2.Apache ...

  6. Axios 使用文档

    Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中. 使用实例:http://www.cnblogs.com/coolslider/p/7838309.ht ...

  7. 关于使用Git的几点小技巧

    告诉git忽略对已经纳入版本管理的文件a的修改,git会一直忽略此文件直到重新告诉git可以再次跟踪此文件: git update-index --assume-unchanged a 告诉git恢复 ...

  8. print语句中逗号(,)和反斜杠(\)的区别

    逗号结尾:   禁止输出换行反斜杠结尾:强制输出换行 >>> print ('A','B') #用一个逗号结尾就可以禁止输出换行 A B >>> print ('A ...

  9. R语言中函数调试

    有时候会用R语言写一下简单的脚本处理函数,加入需要调试的话可以按照下面的步骤进行: fun <- function(x , y){ x + y x - y x * y x / y } debug ...

  10. Linux服务器搭建相关教程链接整理

    Linux: Linux 教程 | 菜鸟教程 linux下如何添加一个用户并且让用户获得root权限 - !canfly - 博客园 Git: 在 Linux 下搭建 Git 服务器 - 黄棣-dee ...