一、前言
1.1 简介
RxJava
带来编码流畅性,map
、flatmap
、filter
等通过链式操作,既避免回调地狱又解决线程频繁切换的问题。应用最多的场景如网络访问后回调主线程显示结果,如果界面已经退出但订阅没有解除,那Activity
或Fragment
句柄会被Observer
长期持有导致内存泄漏。
1.2 传统方案
传统解决办法是构造RxJava
时管理Disposable
,onDestroy
集中解除绑定:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
private CompositeDisposable mCompositeDisposable = new CompositeDisposable();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// This is an example that do something useless.
Disposable disposable = Observable.just(1)
.map(integer -> "Map to String: " + integer)
.filter(s -> !s.isEmpty())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(s -> Toast.show(this, s));
mCompositeDisposable.add(disposable); // 集中管理
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mCompositeDisposable != null) { // 解除所有订阅
mCompositeDisposable.dispose();
}
}
上述方案缺点模板代码多不简洁。
1.3 新办法
为了避免写模板代码引入RxLifecycle
,代码增加.compose(bindToLifecycle())
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// This is an example that do something useless.
Observable.just(1)
.compose(bindToLifecycle())
.map(integer -> "Map to string: " + integer)
.filter(s -> !s.isEmpty())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(s -> ToastUtils.show(this, s));
}
RxLifecycle
缺点这篇文章不会详细说,有兴趣的可以阅读原作者写的文章(英文):为什么不要用RxLifecycle。
二、源码
2.1 类签名
抽象类的父类是AppCompatActivity
,实现LifecycleProvider<ActivityEvent>
接口。
1
2
public abstract class RxAppCompatActivity extends AppCompatActivity
implements LifecycleProvider<ActivityEvent>
实现LifecycleProvider<ActivityEvent>
接口增加了三个方法,并维护了一个BehaviorSubject
实例,该实例是Subject
的子类,实现在RxJava
中,ActivityEvent
放在文章最后简略展示。
1
private final BehaviorSubject<ActivityEvent> lifecycleSubject = BehaviorSubject.create();
2.2 抽象接口
LifecycleProvider
是RxLifecycle
功能的抽象接口。RxLifecycle
只对几个基本组件的实现了LifecycleProvider
,没覆盖自定义组件的部分。所以我们通过实现这个接口,给自己的组件增加RxLifecycle
的能力。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// activity 和 fragment lifecycle providers公共的基本接口
public interface LifecycleProvider<E> {
// @return lifecycle事件序列
@Nonnull
@CheckReturnValue
Observable<E> lifecycle();
// 绑定一个源,直到一个特定的事件发生(该事件就是手动绑定需结束事件的生命周期)
@Nonnull
@CheckReturnValue
<T> LifecycleTransformer<T> bindUntilEvent(@Nonnull E event);
// 绑定一个源,直到下一个合理的事件发生
@Nonnull
@CheckReturnValue
<T> LifecycleTransformer<T> bindToLifecycle();
}
除此之外,把抽象和实现分离,通过抽象指导实现也是常用的设计模式思维之一。
2.3 实现接口
2.3.1 lifecycle
一共实现了三个接口,主要看后面两个。
1
2
3
4
5
6
7
8
private final BehaviorSubject<ActivityEvent> lifecycleSubject = BehaviorSubject.create();
@Override
@NonNull
@CheckResult
public final Observable<ActivityEvent> lifecycle() {
return lifecycleSubject.hide();
}
bindUntilEvent
和bindToLifecycle
实现生命周期绑定
1
2
3
4
5
6
7
@Nonnull
@CheckReturnValue
<T> LifecycleTransformer<T> bindUntilEvent(@Nonnull E event);
@Nonnull
@CheckReturnValue
<T> LifecycleTransformer<T> bindToLifecycle();
2.3.2 bindUntilEvent
bindUntilEvent()
是手动指定观察者取消订阅时的生命周期,不关心所在生命周期的状态。
1
2
3
4
5
6
@Override
@NonNull
@CheckResult
public final <T> LifecycleTransformer<T> bindUntilEvent(@NonNull ActivityEvent event) {
return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
}
例如在onDestroy
中解除绑定。
1
.bindUntilEvent(ActivityEvent.DESTROY)
2.3.3 bindToLifecycle
bindToLifecycle()
根据绑定时所处生命周期,自动在合理的生命周期中解除订阅。
1
2
3
4
5
6
@Override
@NonNull
@CheckResult
public final <T> LifecycleTransformer<T> bindToLifecycle() {
return RxLifecycleAndroid.bindActivity(lifecycleSubject);
}
2.4 生命周期绑定
Activity
每个生命周期的lifecycleSubject
发射相应所在生命周期的事件。同理onStart
到onDestroy
也完全一样。例如在Activity
中:
onCreate()
绑定 –>onDestroy()
解除订阅onStart()
绑定 –>onStop()
解除订阅onResume()
绑定 –>onPause()
解除订阅
下面仅取onCreate
作为实例:
1
2
3
4
5
6
@Override
@CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
lifecycleSubject.onNext(ActivityEvent.CREATE);
}
2.4.1 LifecycleTransformer
LifecycleTransformer
类实现了多个接口,成员方法利用takeUntil
的特性,当第二个Observable发射了一项数据或者终止时,丢弃原始Observable发射的任何数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// Transformer that continues a subscription until a second Observable emits an event.
@ParametersAreNonnullByDefault
public final class LifecycleTransformer<T> implements ObservableTransformer<T, T>,
FlowableTransformer<T, T>,
SingleTransformer<T, T>,
MaybeTransformer<T, T>,
CompletableTransformer
{
final Observable<?> observable;
LifecycleTransformer(Observable<?> observable) {
checkNotNull(observable, "observable == null");
this.observable = observable;
}
@Override
public ObservableSource<T> apply(Observable<T> upstream) {
return upstream.takeUntil(observable);
}
@Override
public Publisher<T> apply(Flowable<T> upstream) {
return upstream.takeUntil(observable.toFlowable(BackpressureStrategy.LATEST));
}
@Override
public SingleSource<T> apply(Single<T> upstream) {
return upstream.takeUntil(observable.firstOrError());
}
@Override
public MaybeSource<T> apply(Maybe<T> upstream) {
return upstream.takeUntil(observable.firstElement());
}
@Override
public CompletableSource apply(Completable upstream) {
return Completable.ambArray(upstream,
observable.flatMapCompletable(Functions.CANCEL_COMPLETABLE));
}
}
2.4.2 RxLifecycle
RxLifeCycle
利用BehaviorSubject
来观察生命周期的变化,通过takeUtil
,令原Observable
监视Subject
发射的数据,当Subject
发出信号时,Observable
后续的数据就会无法发射。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
public class RxLifecycle {
private RxLifecycle() {
throw new AssertionError("No instances");
}
// 绑定给定的事件到lifecycle
@Nonnull
@CheckReturnValue
public static <T, R> LifecycleTransformer<T> bindUntilEvent(@Nonnull final Observable<R> lifecycle,
@Nonnull final R event) {
checkNotNull(lifecycle, "lifecycle == null");
checkNotNull(event, "event == null");
return bind(takeUntilEvent(lifecycle, event));
}
private static <R> Observable<R> takeUntilEvent(final Observable<R> lifecycle, final R event) {
return lifecycle.filter(new Predicate<R>() {
@Override
public boolean test(R lifecycleEvent) throws Exception {
// 生命周期和指定事件匹配返回true
return lifecycleEvent.equals(event);
}
});
}
// 绑定给定源到lifecycle
@Nonnull
@CheckReturnValue
public static <T, R> LifecycleTransformer<T> bind(@Nonnull final Observable<R> lifecycle) {
return new LifecycleTransformer<>(lifecycle);
}
// 绑定给定源到lifecycle
@Nonnull
@CheckReturnValue
public static <T, R> LifecycleTransformer<T> bind(@Nonnull Observable<R> lifecycle,
@Nonnull final Function<R, R> correspondingEvents) {
checkNotNull(lifecycle, "lifecycle == null");
checkNotNull(correspondingEvents, "correspondingEvents == null");
return bind(takeUntilCorrespondingEvent(lifecycle.share(), correspondingEvents));
}
private static <R> Observable<Boolean> takeUntilCorrespondingEvent(final Observable<R> lifecycle,
final Function<R, R> correspondingEvents) {
return Observable.combineLatest(
lifecycle.take(1).map(correspondingEvents),
lifecycle.skip(1),
new BiFunction<R, R, Boolean>() {
@Override
public Boolean apply(R bindUntilEvent, R lifecycleEvent) throws Exception {
return lifecycleEvent.equals(bindUntilEvent);
}
})
.onErrorReturn(Functions.RESUME_FUNCTION)
.filter(Functions.SHOULD_COMPLETE);
}
}
2.5 Subject
上面还出现了BehaviorSubject
,只看看他继承的父类Subject
。这个类直接继承了Observable<T>
,表明是被观察者;又实现Observer<T>
,所以也能作为一名观察者。作为两个角色都兼顾的类,对上级的被观察者身份是观察者,对下级观察者身份是被观察者。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public abstract class Subject<T> extends Observable<T> implements Observer<T> {
public abstract boolean hasObservers();
public abstract boolean hasThrowable();
public abstract boolean hasComplete();
@Nullable
public abstract Throwable getThrowable();
@NonNull
public final Subject<T> toSerialized() {
if (this instanceof SerializedSubject) {
return this;
}
return new SerializedSubject<T>(this);
}
}
2.6 Event分类
ActivityEvent
的生命周期枚举值
1
2
3
4
5
6
7
8
public enum ActivityEvent {
CREATE,
START,
RESUME,
PAUSE,
STOP,
DESTROY
}
FragmentEvent
的生命周期枚举值,里面没有onActivityCreated
,所以建议用CREATE_VIEW
代替。
1
2
3
4
5
6
7
8
9
10
11
12
public enum FragmentEvent {
ATTACH,
CREATE,
CREATE_VIEW,
START,
RESUME,
PAUSE,
STOP,
DESTROY_VIEW,
DESTROY,
DETACH
}