行则将至

人生在勤,不索何获

0%

RxLifecycle 使用详解

原文地址 blog.csdn.net

Github: RxLifecycle

RxLifecycle 依赖

  • 注意:本文使用的版本是 4.0.2 版本
1
2
3
4
5
6
7
8
9
10
// RxLifecycle  
implementation 'com.trello.rxlifecycle4:rxlifecycle:4.0.2'
implementation 'com.trello.rxlifecycle4:rxlifecycle-android:4.0.2'
implementation 'com.trello.rxlifecycle4:rxlifecycle-components:4.0.2'
implementation 'com.trello.rxlifecycle4:rxlifecycle-components-preference:4.0.2'
implementation 'com.trello.rxlifecycle4:rxlifecycle-android-lifecycle:4.0.2'
implementation 'com.trello.rxlifecycle4:rxlifecycle-kotlin:4.0.2'
implementation 'com.trello.rxlifecycle4:rxlifecycle-android-lifecycle-kotlin:4.0.2'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
annotationProcessor 'androidx.lifecycle:lifecycle-compiler:2.3.1'

RxLifecycle 介绍

RxLifecycle 目的:解决 RxJava 使用中的==内存泄漏==问题。

RxLifecycle 核心思想:通过监听 Activity、Fragment 的生命周期,来自动==断开订阅==防止内存泄漏。

例如,当使用 RxJava 订阅并执行耗时任务后,当 Activity 被 finish 时,如果耗时任务还未完成,没有及时取消订阅,就会导致 Activity 无法被回收,从而引发内存泄漏。

为了解决这个问题,就产生了 RxLifecycle,让 RxJava 变得有生命周期感知,使得其能及时取消订阅,避免出现内存泄漏问题。

它可以让 Observable 发布的事件和当前的组件绑定,实现生命周期同步。
从而实现当前组件生命周期结束时,自动取消对 Observable 订阅。

目前网上对 RxJava 的内存泄漏有几种方案

  1. 手动为 RxJava 的每一次订阅进行控制,指定在哪个生命周期方法调用时取消订阅;
  2. 当前组件生命周期结束时,自动取消对 Observable 订阅

上述两种方式我都使用过,RxLifecycle 显然对于第一种方式,更简单直接,并且能够在 Activity/Fragment 容器的指定生命周期取消订阅,实在是好用。

RxJava 的内存泄漏案例

每隔 1 秒打印,无限循环:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e("xyh", "onCreate: ");
Observable.interval(2, 1, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) // interval 默认在新线程,所以需要切换回主线程
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
Log.e("xyh", +aLong + "");
}
});
}

@Override
protected void onDestroy() {
super.onDestroy();
Log.e("xyh", "onDestroy: ");
}
}

打印结果

1
2
3
4
5
6
7
8
9
2020-03-11 22:10:09.004 15261-15261/com.xyh.rxlifecycle E/xyh: onCreate: 
2020-03-11 22:10:11.029 15261-15261/com.xyh.rxlifecycle E/xyh: 0
2020-03-11 22:10:12.029 15261-15261/com.xyh.rxlifecycle E/xyh: 1
2020-03-11 22:10:13.029 15261-15261/com.xyh.rxlifecycle E/xyh: 2
2020-03-11 22:10:14.028 15261-15261/com.xyh.rxlifecycle E/xyh: 3
2020-03-11 22:10:15.050 15261-15261/com.xyh.rxlifecycle E/xyh: onDestroy:
2020-03-11 22:10:15.061 15261-15261/com.xyh.rxlifecycle E/xyh: 4
2020-03-11 22:10:16.029 15261-15261/com.xyh.rxlifecycle E/xyh: 5
2020-03-11 22:10:17.028 15261-15261/com.xyh.rxlifecycle E/xyh: 6

我们发现执行 onDestroy() 方法后,还会继续执行,因为没有及时解除订阅,在退出 activity 的时候,异步线程还在执行,对 activity 还存在引用,此时就会产生内存泄漏。

RxLifecycle 的使用 (继承)

添加依赖

1
2
3
4
//处理rxjava内存泄漏   
implementation 'com.trello.rxlifecycle4:rxlifecycle:4.0.2'
implementation 'com.trello.rxlifecycle4:rxlifecycle-android:4.0.2'
implementation 'com.trello.rxlifecycle4:rxlifecycle-components:4.0.2'

Activity/Fragment 需继承 RxAppCompatActivity/RxFragment,目前支持的有如下:

1. 继承 RxAppCompatActivity :

Activity 需要继承 RxAppCompatActivity,Fragment 需要继承 RxFragment。

1
2
3
4
public class MainActivity extends RxAppCompatActivity {
...
...
}

在项目中针对 base 类的容器中继承实现对应的 Rx 类即可

1
2
3
public abstract class BaseActivity extends RxAppCompatActivity {

}

2. 使用 compose 操作符绑定容器生命周期

有两种方式:

方式 1:使用 bindToLifecycle()

以 Activity 为例,在 Activity 中使用 bindToLifecycle() 方法,完成 Observable 发布的事件和当前的组件绑定,实现生命周期同步。从而实现当前组件生命周期结束时,自动取消对 Observable 订阅,代码如下:

在 onResume() 进行绑定订阅,则在 onPause() 进行解除订阅,生命周期是两两对应的。

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
public class MainActivity extends RxAppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

Log.e("xyh", "onCreate: ");

//在某个生命周期进行绑定,在对应的生命周期进行订阅解除,当执行onDestory()时, 自动解除订阅
Observable.interval(3, 2, TimeUnit.SECONDS)
.doOnDispose(new Action() {
@Override
public void run() throws Exception {
Log.e("xyh", "解除了订阅");
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.compose(this.<Long>bindToLifecycle())
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
//在onCreate()中启动,一直运行到onDestory()
Log.e("xyh", +aLong + "");
}
});
}

@Override
protected void onDestroy() {
super.onDestroy();
Log.e("xyh", "onDestroy: ");
}
}

方式 2:使用 bindUntilEvent()

使用 ActivityEvent 类,其中的 CREATE、START、 RESUME、PAUSE、STOP、 DESTROY 分别对应生命周期内的方法。使用 bindUntilEvent 指定在哪个生命周期方法调用时取消订阅:

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
public class MainActivity extends RxAppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

Log.e("xyh", "onCreate: ");

Observable.interval(3, 2, TimeUnit.SECONDS)
.doOnDispose(new Action() {
@Override
public void run() throws Exception {
Log.e("xyh", "解除了订阅");
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
// 手动指定在生命周期onDestory()时,取消订阅。
.compose(this.<Long>bindUntilEvent(ActivityEvent.DESTROY))
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
//在onCreate()中启动,一直运行到onDestory()
Log.e("xyh", +aLong + "");
}
});
}

@Override
protected void onDestroy() {
super.onDestroy();
Log.e("xyh", "onDestroy: ");
}
}

打印结果:

我们发现执行,在退出 activity 的时候,解除了订阅,不再继续执行,解决类内存泄漏。

1
2
3
4
5
6
04-03 17:10:38.296 29186-29186/? E/xyh: onCreate: 
04-03 17:10:41.311 29186-29219/com.xiaoyehai.rxlifecycle E/xyh: 0
04-03 17:10:43.310 29186-29219/com.xiaoyehai.rxlifecycle E/xyh: 1
04-03 17:10:45.311 29186-29219/com.xiaoyehai.rxlifecycle E/xyh: 2
04-03 17:10:46.723 29186-29186/com.xiaoyehai.rxlifecycle E/xyh: 解除了订阅
04-03 17:10:46.724 29186-29186/com.xiaoyehai.rxlifecycle E/xyh: onDestroy:

以 Activity 为例,主要有如下两种方法:

1
2
3
4
bindToLifecycle()  //在某个生命周期进行绑定,在对应的生命周期进行订阅解除。
//在onResume()进行绑定订阅,则在onPause()进行解除订阅,生命周期是两两对应的。

bindUntilEvent(@NonNull ActivityEvent event) //该方法指定在哪个生命周期方法调用时取消订阅。

Fragment 也有同样的两种方法,只是方法名会有所不同。

其中 ActivityEvent 是一个枚举类,对应于 Activity 的生命周期:

1
2
3
4
5
6
7
8
9
10
public enum ActivityEvent {

CREATE,
START,
RESUME,
PAUSE,
STOP,
DESTROY

}

LifecycleProvider 的使用 (非继承)

上面的方式需要继承 RxAppCompatActivity,如果我们自己有 BaseActivity,所以不能继承 RxActvivty,RxAppCompatActivity、RxFragment,NaviActivity。

为了保持代码的灵活性,我们只需要添加下面的依赖即可:

1
2
// 使用Android生命周期作为提供者
implementation 'com.trello.rxlifecycle3:rxlifecycle-android-lifecycle:3.1.0'
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
public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e("xyh", "onCreate: ");

LifecycleProvider<Lifecycle.Event> provider = AndroidLifecycle.createLifecycleProvider(this);
Observable.interval(3, 2, TimeUnit.SECONDS)
.doOnDispose(new Action() {
@Override
public void run() throws Exception {
Log.e("xyh", "解除了订阅");
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.compose(provider.<Long>bindToLifecycle())
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
//在onCreate()中启动,一直运行到onDestory()
Log.e("xyh", +aLong + "");
}
});
}

@Override
protected void onDestroy() {
super.onDestroy();
Log.e("xyh", "onDestroy: ");
}
}
1
2
3
4
2020-03-11 22:19:29.329 16751-16751/com.xyh.rxlifecycle E/xyh: 0
2020-03-11 22:19:31.327 16751-16751/com.xyh.rxlifecycle E/xyh: 1
2020-03-11 22:19:33.108 16751-16751/com.xyh.rxlifecycle E/xyh: 解除了订阅
2020-03-11 22:19:33.111 16751-16751/com.xyh.rxlifecycle E/xyh: onDestroy:

把 LifecycleProvider 抽取到 BaseActivity 中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public abstract class BaseActivity extends AppCompatActivity {

protected LifecycleProvider<Lifecycle.Event> mLifecycleProvider;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutId());

mLifecycleProvider = AndroidLifecycle.createLifecycleProvider(this);

init();
}

protected abstract int getLayoutId();

protected abstract void init();
}
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
public class MainActivity extends BaseActivity {

@Override
protected int getLayoutId() {
return R.layout.activity_main;
}

@Override
protected void init() {
Log.e("xyh", "init: ");
Observable.interval(2, 1, TimeUnit.SECONDS)
.doOnDispose(new Action() {
@Override
public void run() throws Exception {
Log.e("xyh", "解除了订阅");
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.compose(mLifecycleProvider.<Long>bindToLifecycle())
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
//在onCreate()中启动,一直运行到onDestory()
Log.e("xyh", +aLong + "");
}
});
}

@Override
protected void onDestroy() {
super.onDestroy();
Log.e("xyh", "onDestroy: ");
}
}

这里我们要用到 LifecycleProvide 这个接口。值得一提的是这个接口已经在 RxAppCompatActivity 中实现了,所以为什么可以继承 RxAppCompatActivity,赋予接口引用就可以使用它了。

MVP 中使用 RxLifecycle

这只是一个很简单的 mvp 案例,主要是演示 RxLifecycle 在 mvp 中的使用,在项目实际开发中可以进行封装。

不需要继承 RxAppCompatActivity/RxFragment 方式

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
public class MainActivity extends BaseActivity implements MainView {

@Override
protected int getLayoutId() {
return R.layout.activity_main;
}

@Override
protected void init() {
Log.e("xyh", "init: ");
MainPresenter mainPresenter = new MainPresenter(mLifecycleProvider, this);
mainPresenter.loadData();
}

@Override
public void onSuccess(String s) {
Log.e("xyh", "onSuccess: " + s);
}

@Override
protected void onDestroy() {
super.onDestroy();
Log.e("xyh", "onDestroy: ");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
public class MainModel {

public Observable<Long> loadData() {

Observable<Long> observable =
Observable
.interval(2, 1, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());

return 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
public class MainPresenter {

public LifecycleProvider<Lifecycle.Event> lifecycleProvider;
public MainView mainView;
private final MainModel mMainModel;

public MainPresenter(LifecycleProvider<Lifecycle.Event> lifecycleProvider, MainView mainView) {
this.lifecycleProvider = lifecycleProvider;
this.mainView = mainView;
mMainModel = new MainModel();
}

public void loadData() {
mMainModel.loadData()
.doOnDispose(new Action() {
@Override
public void run() throws Exception {
Log.e("xyh", "解除了订阅");
}
})
.compose(lifecycleProvider.<Long>bindToLifecycle())
.subscribe(new Observer<Long>() {
@Override
public void onSubscribe(Disposable d) {

}

@Override
public void onNext(Long aLong) {
mainView.onSuccess(aLong + "");
}

@Override
public void onError(Throwable e) {

}

@Override
public void onComplete() {

}
});


}
}

使用继承 RxAppCompatActivity/RxFragment 方式

1
2
MainPresenter mainPresenter = new MainPresenter(bindToLifecycle(), this);
mainPresenter.loadData();
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
public class MainPresenter {

public LifecycleTransformer lifecycleTransformer;
public MainView mainView;
private final MainModel mMainModel;

public MainPresenter(LifecycleTransformer lifecycleTransformer, MainView mainView) {
this.lifecycleTransformer = lifecycleTransformer;
this.mainView = mainView;
mMainModel = new MainModel();
}

public void loadData() {
mMainModel.loadData()
.doOnDispose(new Action() {
@Override
public void run() throws Exception {
Log.e("xyh", "解除了订阅");
}
})
.compose(lifecycleTransformer)
.subscribe(new Observer<Long>() {
@Override
public void onSubscribe(Disposable d) {

}

@Override
public void onNext(Long aLong) {
mainView.onSuccess(aLong + "");
}

@Override
public void onError(Throwable e) {

}

@Override
public void onComplete() {

}
});
}
}

Fragment 中使用 RxLifecycle

Fragment 中使用和在 Activity 中的使用基本一致。

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
public abstract class BaseFragment extends Fragment {

protected LifecycleProvider<Lifecycle.Event> mLifecycleProvider;

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view=inflater.inflate(getLayoutId(),container,false);
return view;
}

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mLifecycleProvider = AndroidLifecycle.createLifecycleProvider(this);
//要用this,he fragment的生命周期绑定在一起如果使用getActivity()的话就是和Activity的生命周期绑定在一起
//mLifecycleProvider = AndroidLifecycle.createLifecycleProvider(getActivity());


init();

}

protected abstract int getLayoutId();

protected abstract void init();


}
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
public class HomeFrgament extends BaseFragment {
@Override
protected int getLayoutId() {
return R.layout.fragment_home;
}

@Override
protected void init() {

Log.e("xyh", "init: ");
Observable.interval(2, 1, TimeUnit.SECONDS)
.doOnDispose(new Action() {
@Override
public void run() throws Exception {
Log.e("xyh", "解除了订阅");
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.compose(mLifecycleProvider.<Long>bindToLifecycle())
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
//在onCreate()中启动,一直运行到onDestory()
Log.e("xyh", +aLong + "");
}
});
}

@Override
public void onDestroyView() {
super.onDestroyView();
Log.e("xyh", "HomeFrgament==onDestroyView: " );
}

@Override
public void onDestroy() {
super.onDestroy();
Log.e("xyh", "HomeFrgament==onDestroy: " );
}
}