Android架构设计Android

放弃RxBus,拥抱RxJava(一):为什么避免使用Event

2017-03-31  本文已影响10856人  W_BinaryTree

EventBus和Otto在之前作为Android组件间通信工具,简单方便十分受欢迎,但是也非常容易Abuse。大概有如下几个缺点:

由于EventBus的种种缺点,以及后面RxJava的出现。很多人都开始使用RxJava来取代EventBus。甚至Otto的官方介绍里都写到:

Deprecated!

This project is deprecated in favor of RxJava and
RxAndroid. These projects permit the same event-driven
programming model as Otto, but they’re more capable and offer better control of threading.

If you’re looking for guidance on migrating from Otto to Rx, this post
is a good start.

链接是一个教你怎么使用RxJava来自己手动写一个RxBus来代替EventBus的文章。虽然看起来是在用RxJava。但是实际上却仍然在用EventBus。甚至这个封装其实也并没有GreenRobot或者Otto来的好。
我们看看Jake Wharton对RxBus的评价:


我想"RxBus"唯一的好处就是他是一个Rx的入门毒品。否则的话,你要么就不是在用Rx,要么你需要更加惯用的Rx资源 (渣翻译见谅)

再来一个GitHub的:


subscribeActual部分我们先不考虑。然而Jake指出最好不要使用Relay来“重新发明”Event Bus.

这里看图说话:
Jake Wharton在GOTO 2016 上的讲座中提到,我们正常的Android编程是这样的:



我们像一个中间人一样。
而使用RxJava。 我们的结构,更像这样



我们使用RxJava来直接把组件相连,对所接受到的数据作出反应,所谓的 "Reactive"。
而使用Eventbus? Jake 没说, 我自己画一个:

我们作为一个中间人,传递消息。EventBus作为另一个中间人。帮我们传递消息。(这也就是所谓的“看似解耦”)

再打个比方,虽然我们将EventBus翻译成时间总线,但是其实总线就是Bus也就是公交车。而RxJava更像一个专车,Uber或者滴滴。他直接链接你的两个或多个需要通信的类。传输数据,当然你可以做一个很大的专车,穿梭在所有类之间,也就是所谓的RxBus。所以在这里为什么放弃RxBus也就不言而喻了不是?

那么,问题来了?

怎样才是正确(正常?)的RxJava使用方式?

其实Jake 也在GitHub的讨论上给出了一个答案:


所以应该是,每当你想发布一个Event在EventBus时,直接暴露一个Observable出来。每当你想接受一个Event时,找到这个Observable并且Subscribe他。

这样做的好处是什么?

我们来举个例子

上下两个Fragment,上面的一个EditText,下面的一个TextView。上面的EditText变化的时候下面的TextView也跟着变化。

先把EditText的TextChangedListener封装在Observable里:

        stringObservable = Observable.create(e -> editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                e.onNext(s.toString());
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        }));

/**
***
*/
    //Expose Observable
    public Observable<String> getEditTextObservable() {
        return stringObservable;
    }```
不习惯自己封装可以使用RxBinding :
    stringObservable = RxTextView.textChangeEvents(editText)
                                 .map(event -> event.text().toString());
再从我们的TextViewFragment中 取到这个封装好的Observable:
@Override
public void onStart() {
    super.onStart();
    FragmentEditText fragment = (FragmentEditText) getFragmentManager().findFragmentByTag(FragmentEditText.TAG);
    if(fragment != null){
        fragment.getStringObservable().subscribe(s -> textView.setText(s));
    }
}
来看看效果:

![](http:https://img.haomeiwen.com/i2417399/f008642da01d310f.gif?imageMogr2/auto-orient/strip)

当然,这里还有个问题
- 由于我们将editText封装在Observable里,无论是create()方法还是使用RxBinding,都会持有这个View的强引用。造成内存泄漏。所以我们一定要在最后加入dispose()方法来释放。所以我推荐使用RxBinding,他已经帮我们在dispose()方法里写好了解除Listener的方法。
- 因为并没有使用publish操作符,导致多个Subscriber的时候还是有些许问题。可以考虑直接加入.share().

具体我们如何讲常用的数据/Callback封装到Observable中。我会在接下来的文章中写到。
>  [第二篇链接](http://www.jianshu.com/p/d2df6bceeff9) 
上一篇 下一篇

猜你喜欢

热点阅读