RxLifecycle依赖
- 注意:本文使用的版本是3.1版本
implementation 'com.trello.rxlifecycle3:rxlifecycle:3.1.0'
// If you want to bind to Android-specific lifecycles
implementation 'com.trello.rxlifecycle3:rxlifecycle-android:3.1.0'
// If you want pre-written Activities and Fragments you can subclass as providers
implementation 'com.trello.rxlifecycle3:rxlifecycle-components:3.1.0'
// If you want pre-written support preference Fragments you can subclass as providers
implementation 'com.trello.rxlifecycle3:rxlifecycle-components-preference:3.1.0'
// If you want to use Android Lifecycle for providers
implementation 'com.trello.rxlifecycle3:rxlifecycle-android-lifecycle:3.1.0'
// If you want to use Kotlin syntax
implementation 'com.trello.rxlifecycle3:rxlifecycle-kotlin:3.1.0'
// If you want to use Kotlin syntax with Android Lifecycle
implementation 'com.trello.rxlifecycle3:rxlifecycle-android-lifecycle-kotlin:3.1.0'
// If you want to use Navi for providers
// DEPRECATED: Use rxlifecycle-android-lifecycle instead. This will be removed in a future release.
implementation 'com.trello.rxlifecycle3:rxlifecycle-navi:3.1.0'
RxLifecycle介绍
RxLifecycle目的:解决RxJava使用中的内存泄漏问题。
RxLifecycle核心思想:通过监听Activity、Fragment的生命周期,来自动断开订阅防止内存泄漏。
例如,当使用RxJava订阅并执行耗时任务后,当Activity被finish时,如果耗时任务还未完成,没有及时取消订阅,就会导致Activity无法被回收,从而引发内存泄漏。
为了解决这个问题,就产生了RxLifecycle,让RxJava变得有生命周期感知,使得其能及时取消订阅,避免出现内存泄漏问题。
它可以让Observable发布的事件和当前的组件绑定,实现生命周期同步。
从而实现当前组件生命周期结束时,自动取消对Observable订阅。
目前网上对RxJava的内存泄漏有几种方案
- 手动为RxJava的每一次订阅进行控制,指定在哪个生命周期方法调用时取消订阅;
- 当前组件生命周期结束时,自动取消对Observable订阅
上述两种方式我都使用过,RxLifecycle显然对于第一种方式,更简单直接,并且能够在Activity/Fragment容器的指定生命周期取消订阅,实在是好用。
RxJava的内存泄漏案例
每隔1秒打印,无限循环:
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: ");
}
}
打印结果
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的使用
添加依赖
//处理rxjava内存泄漏
implementation 'com.trello.rxlifecycle3:rxlifecycle:3.1.0'
implementation 'com.trello.rxlifecycle3:rxlifecycle-android:3.1.0'
implementation 'com.trello.rxlifecycle3:rxlifecycle-components:3.1.0'
Activity/Fragment需继承RxAppCompatActivity/RxFragment,目前支持的有如下:
1. 继承RxAppCompatActivity :
Activity需要继承RxAppCompatActivity,Fragment需要继承RxFragment。
public class MainActivity extends RxAppCompatActivity {
...
...
}
在项目中针对base类的容器中继承实现对应的Rx类即可
public abstract class BaseActivity extends RxAppCompatActivity {
}
2. 使用compose操作符绑定容器生命周期
有两种方式:
方式1:使用bindToLifecycle()
以Activity为例,在Activity中使用bindToLifecycle()方法,完成Observable发布的事件和当前的组件绑定,实现生命周期同步。从而实现当前组件生命周期结束时,自动取消对Observable订阅,代码如下:
在onResume()进行绑定订阅,则在onPause()进行解除订阅,生命周期是两两对应的。
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指定在哪个生命周期方法调用时取消订阅:
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)) // 手动指定在生命周期onDestory()时,取消订阅。
.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的时候,解除了订阅,不再继续执行,解决类内存泄漏。
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为例,主要有如下两种方法:
bindToLifecycle() //在某个生命周期进行绑定,在对应的生命周期进行订阅解除。
//在onResume()进行绑定订阅,则在onPause()进行解除订阅,生命周期是两两对应的。
bindUntilEvent(@NonNull ActivityEvent event) //该方法指定在哪个生命周期方法调用时取消订阅。
Fragment也有同样的两种方法,只是方法名会有所不同。
其中ActivityEvent是一个枚举类,对应于Activity的生命周期:
public enum ActivityEvent {
CREATE,
START,
RESUME,
PAUSE,
STOP,
DESTROY
}
不需要继承RxAppCompatActivity/RxFragment实现
上面的方式需要继承RxAppCompatActivity,如果我们自己有BaseActivity,所以不能继承RxActvivty,RxAppCompatActivity、RxFragment,NaviActivity。
为了保持代码的灵活性,我们只需要添加下面的依赖即可:
// 使用Android生命周期作为提供者
implementation 'com.trello.rxlifecycle3:rxlifecycle-android-lifecycle:3.1.0'
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: ");
}
}
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中
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();
}
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方式
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: ");
}
}
public class MainModel {
public Observable<Long> loadData() {
Observable<Long> observable =
Observable
.interval(2, 1, TimeUnit.SECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
return observable;
}
}
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方式
MainPresenter mainPresenter = new MainPresenter(bindToLifecycle(), this);
mainPresenter.loadData();
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中的使用基本一致。
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();
}
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: " );
}
}