我们为什么要在Android中使用RxJava

感觉RxJava最近风生水起,不学习一下都不好意思了,洒家也是初学RxJava,也是感觉代码好像更复杂更难懂了,看了一篇外文感同身受,简单翻译一下。本文简单介绍使用RxJava优势所在。但可能需要有一点RxJava基础,推荐先看一下抛物线的那篇经典的匠心写作。

—–华丽分割线,译文开始———

Reactive Extensions (Rx) 是一系列接口和方法,为开发者提供了一种易懂且迅速简单易维护的方法。RxJava就是干这事儿的,提供一系列tools来帮你写出简洁的代码。

老实说,一开始我认为RxJava 写的代码理解起来很困难,并且引入一个库,单单就是为了用用这种新式的api,这困扰到了我。后来,我懂了。以传统的编码方式,随着app的发展,我需要重构代码、一遍一遍的重复样板代码,以满足用户不断变更的新需求,这让我苦不堪言。

我做的大量工作,其实是改写相关方法和接口,就是因为需求的变更(这是开发与产品间那些血案的原罪)或者需要改变展示的信息亦或是需要改变处理信息数据..这很抓狂。另外,这种代码让其他来维护的人来理解,通常是很耗时的。

举个栗子:我们需要从数据库获取一组用户的链表数据,并展示出来。我们可以用AsyncTask后台查询数据库,获得的结果给Ui的适配器展示出来。简单示例代码:

public class SampleTask extends AsyncTask<Void,Void,List<Users>> {
    private final SampleAdapter mAdapter;

    public SampleTask(SampleAdapter sampleAdapter) {
        mAdapter = sampleAdapater;
    }

    @Override
    protected List<Users> doInBackground(Void... voids) {
        //fetch there results from the database and return them to the onPostExecute
        List<Users> users = getUsersFromDatabase;
        return users;
    }

    @Override
    protected void onPostExecute(List<Users> users) {
        super.onPostExecute(products);
        // Checking if there are users on the database
        if(users == null) {
 //No users, presenting a view saying there are no users
 showEmptyUsersMessageView;
 return;
        }
        for(User user : users){
 mAdapter.add(user);
        }
        mAdapter.notifyDataSetChanged;
    }
}

现在有个新需求,要求只显示非guest的user,我们处理的方法是,在添加到adapter前加个条件判断是不是guset,或者改变数据库查询的条件。更有甚者,你又被要求从数据库中获取另外的其他信息,跟user一并在这个adapter中显示出来呢?

这就是我们为什么要用RxJava了,把我们从这个泥潭中拉出来。换个姿势,我们Rx代码是这样子(假设您已学习过Rx基础用法):

public Observable<List<User>> fetchUsersFromDatabase {
    return Observable.create(new Observable.OnSubscribe<List<User>{
        @Override
        public void call(Subscriber<? super List<User>> subscriber){
 // Fetch information from database
 subscriber.onNext(getUserList);
 subscriber.onCompleted;
        }
    });
}

像这样被调用:

fetchUsersFromDatabase
.subscribeOn(Schedulers.io)
//will process everything in a new thread
.observeOn(AndroidSchedulers.mainThread)
//will listen the results on the main thread
.subscribe(new Subscriber<List<User>> {
 @Override
 public void onCompleted {
 }
 @Override
 public void onError(Throwable e) {
 }
 @Override
 public void onNext(List<User> users) {
 //Do whatever you want with each user
 }
        });

开始改需求了哈 怎么不显示guests呢,RxJava分分钟过滤掉这种不速之客:

fetchUsersFromDatabase
        .filter(new Func1<User, Boolean> {
 @Override
 public Boolean call(User user) {
 //only return the users which are not guests
 return !user.isGuest;
 }
        })
        .subscribeOn(Schedulers.io)
        .observeOn(AndroidSchedulers.mainThread)
        .subscribe(new Subscriber<User> {
 @Override
 public void onCompleted {
 }

 @Override
 public void onError(Throwable e) {
 /*Check if there was any error while retrieving from database*/
 }

 @Override
 public void onNext(User user) {
 //Do whatever you want with each user
 }
 }
        );

传统的方式,即便是个简单的变更,为了保持优雅的接口化编程,我们也得创建新接口,重构代码来实现过滤。但是使用RxJava让这一切变得优雅了,我们只需要一个被观察者用来获取所有的信息,让后你就可以尽情的用这些方法来过滤获取你想要的数据。

可能你又会说了,ok,这是很好很易读的结构,但是这似乎使代码量变多了呢。well you are right,但是这就是Retrolambda闪耀的时候了,这个库为我们兼容了以使用java8 lambda表达式,方法引用等等。

帮我们简化代码如下:

fetchUsersFromDatabase
        .subscribeOn(Schedulers.io)
        .observeOn(AndroidSchedulers.mainThread)
        .subscribe(value -> {
 //Do whatever with the value
 },error -> {
 //do something with in case of error
 }
        );

这个问题完美搞定,然后你又开始问了,我需要增加另外的查询结果和user一同显示在这个adapter中怎么破。这真不是事儿:

fetchUsersFromDatabase
        .zipWith(fetchSomethingElseFromDatabase, (users, somethingElse) -> {
 /*here combine users and something else into a new object*/
        })
        .subscribe( o -> {
 /*use the combine object from users and something else to fill the adapter */
});

如上,我们可以轻松组合数据库查出来的其他数据和users给一个adapter一同显示。是不是更易维护,代码少,易读,清晰?

如果要更深入的学习RXJava可以看下面这篇文章,我看后受益匪浅。

[Party tricks with RxJava, RxAndroid & Retrolambda](https://medium.com/p/1b06ed7cd29c)

相关文章

我的Java!越过山丘

当年我是VS程序员,2000年被微软无情抛弃时,我徘徊过,到底继续跟着微软跑还是甩了它!当时兜里没钱,没法再花精力去学习除了名字很像其他都不一样的VS.net……既然甩了微软,那我为什么不直接选一个跨...

Java内存模型的历史变迁

本文通过介绍Java的新/旧内存模型,来展示Java技术的历史变迁。旧的Java内存模型Java使用的是共享内存的并发模型,在线程之间共享变量。Java语言定义了线程模型规范,通过内存模型控制线程与变...

如何识别Java中的内存泄漏

【编者按】作者Martin Gutenbrunner供职于Ruxit,拥有十年的Java Web应用程序架构和管理经验。近日,他在Dzone上撰文分享了Java内存泄漏识别相关经验,由OneAPM工程...

详解Java中的注解

在Java中,注解(Annotation)引入始于Java5,用来描述Java代码的元信息,通常情况下注解不会直接影响代码的执行,尽管有些注解可以用来做到影响代码执行。注解可以做什么Java中的注解通...

Java反射机制剖析

java反射机制:1.指的是可以于运行时加载,探知和使用编译期间完全未知的类.2.程序在运行状态中, 可以动态加载一个只有名称的类, 对于任意一个已经加载的类,都能够知道这个类的所有属性和方法; 对于...