原文地址 blog.csdn.net
Github: RxLifecycle
RxLifecycle 依赖
1 2 3 4 5 6 7 8 9 10
| 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 的内存泄漏有几种方案
- 手动为 RxJava
的每一次订阅进行控制,指定在哪个生命周期方法调用时取消订阅;
- 当前组件生命周期结束时,自动取消对 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()) .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
| 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,目前支持的有如下:
![](https://img-blog.csdnimg.cn/20200311220545331.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM2Njk5OTMw,size_16,color_FFFFFF,t_70)
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: ");
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 { 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()) .compose(this.<Long>bindUntilEvent(ActivityEvent.DESTROY)) .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: "); } }
|
打印结果:
我们发现执行,在退出 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()
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
| 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 { 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 { 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);
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 { 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: " ); } }
|