RxJava2.0的优点缺点

RxJava自从发布以来被越来越多的公司采用,越来越多的第三方库都开始支持RxJava,如RxBus,BxBinding,Retroft,RxRelay等等,之前都没怎么写过博客,趁着公司搞新技术学习的机会,
学习下RxJava并用博客记录下学习的心得体会.

学习RxJava由于没有对应的文献可以参考,只能通过自己阅读源码,以及通过网上搜资料来学习这一新的代码框架.然而由于RxJava1.0与RxJava2.0之间有较大的区别,作为一个刚刚接触RxJava的同学来说,读对文章很重要,这可以让我们快速了解RxJava,更快的上手.推荐几位大神总结的比较好的关于RxJava的文章:
基于RxJava1.0:http://www.jianshu.com/p/6fd8640046f1
其中RxJava1.0的文章便于我们了解RxJava的优缺点,对RxJava有个大致的认知,便于更深入的学习,读懂做作者大概的意思就行.RxJava2.0的文章系统讲解了RxJava的操作符,体系结构等,建议以第三篇文章为准.

RxJava首先是一个用于基于观察者模式的实现异步操作的库,它的优势总结起来有以下两点:
1.链式调用(结合Retrolambda使用能让代码变得更为优雅)
2.便捷的线程切换
3.简洁
就是RxJava被越来越广泛的被使用的原因.

观察者模式就不多讲了,我们用到的setOnClickListener()等方法就是平时接触到的最常见的观察者模式,现在我们通过一个图片上传的例子来体现RxJava的优点:
业务场景是,用户上传图片审核.我们从将图片压缩之后上传到服务器,获取返回的图片地址,然后在将图片地址+用户信息上传到对应的接口,这样完成一个完整的业务逻辑.
普通写法:

if (resultCode == RESULT_OK) {
                    Uri uri = data.getData();
                    String imageAbsolutePath = UriUtil.getImageAbsolutePath(context, uri);
                    File file = new File(imageAbsolutePath);
                    String compressedPath = compressPic(file);
                    startUpload(compressedPath);
 }

private void startUpload(String filePath) {
        new updateHeadPhoto().execute(filePath);
}
//上传图片
private class updateHeadPhoto extends AsyncTask{
    .....
    onPostExecute(String s){
            new UploadUserInfo(s).excute();
    }
}
//上传用户信息
private class UploadUserInfo{
.....
}

以上的这种写法当然没有问题,但是缺点也很明显,多层嵌套,多个异步任务,代码可读性不佳,而且后台接口使用的是ICE技术,遇上网络请求只能new一个个的AsyncTask,这让代码嵌套层级更多.而且因为上传用户信息的代码是放在上传图片异步任务中的看第一段代码并不能让读者读到完整的业务逻辑
使用RxJava:

if (resultCode == RESULT_OK) {
                    Uri uri = data.getData();
        Observable.just(uri)
                .subscribeOn(Schedulers.io())
                .doOnSubscribe(new Consumer<Disposable>() {
                    @Override
                    public void accept(Disposable disposable) throws Exception {
                        //做一些准备工作如弹出对话框等
                        showLoadingDialog();
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .map(new Function<Uri, String>() {
                    @Override
                    public String apply(Uri uri) throws Exception {
                        return getImagePath(uri);
                    }
                })
                .observeOn(Schedulers.io())
                .map(new Function<String, String>() {
                    @Override
                    public String apply(String s) throws Exception {
                         String compressPath = compressImage(s);
                        String serverPath = uploadPic(compressPath);
                        String json = uploadUserInfo();
                        return json;
                        return json;
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                    }

                    @Override
                    public void onNext(String value) {
                        Toast.makeText(NetWorkExampleActivity.this, "图片上传失败", Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onError(Throwable e) {
                        Toast.makeText(NetWorkExampleActivity.this, "图片上传失败", Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onComplete() {

                    }
                });

    }
 }

读到这里可能有人要说了,这没见代码减少多少啊,哪来的简洁.但仔细一读会发现代码没见有有减少多少,但是逻辑简洁了很多,而且几乎都不需要考虑线程切换的问题,通过observerOn这个方法就能便捷的实现线程之间的切换,而且代码的链式操作,采用数据流的形式,可以说一路看到底业务逻辑基本就能有大致的了解,这对我们阅读代码的效率可以有很大的提升.

在开发中程序员最深恶痛绝的一件事就是阅读别人的代码,各种回调,反复的嵌套,线程之间的各种切换,在加上一些随机命名法,让人抓狂.但是当接手项目的程序员有使用RxJava的经验,并且接手的项目是基于RxJava开发的.上手这个项目的时候,读代码就会像读业务流图一样不再是一件让人痛苦的事,这样能大大降低出bug的几率以及提高熟悉业务的速度.

而且结合上lambda表达式代码变成了这样:

Observable.just(uri)
                .subscribeOn(Schedulers.io())
                .doOnSubscribe(disposable -> {
                    //做一些准备工作如弹出对话框等
                    showLoadingDialog();
                })
                .observeOn(AndroidSchedulers.mainThread())
                .map(uri1 -> getImagePath(uri1))
                .observeOn(Schedulers.io())
                .map(s -> {
                    //压缩图片
                    String compressPath = compressImage(s);
                    //上传图片
                    String serverPath = uploadPic(compressPath);
                    //上传图片和用户的审核信息
                    String json = uploadUserInfo();
                    return json;
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<String>() {
                    @Override
                    public void onSubscribe(Disposable d) {
                    }

                    @Override
                    public void onNext(String value) {
                       //对json进行解析,业务逻辑进行处理
                    }

                    @Override
                    public void onError(Throwable e) {
                    //网络请求失败等状况
                        Toast.makeText(NetWorkExampleActivity.this, "图片上传失败", Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onComplete() {

                    }
                });

代码变的更加简洁美观,这也加快了我们的阅读效率.

当然拥有如此强大功能的一个异步操作库,还有一大堆流行的第三方库加入Rx阵营,入手起来肯定不容易,他有功能强大但也很繁杂的各种操作符,各种定制的有特殊功用的观察者被观察者,还有背压的概念…

但是把代码写的像业务流图一样清晰明了,一直是每一个程序员的梦想,是时候入手RxJava了.