MiQing Blog

无惧艰难,让生活更幸福更充实,努力起飞!

0%

【Android-开发框架搭建】-处理Rxjava内存泄漏的两种方式-Rxlifecycle2、Autodispose

前言

在Rxjava满大街跑的时代,使用过程中无法避免会有Rxjava资源回收处理不到位的地方,笔者深受其危害。当页面被销毁的时候,
未正确处理取消订阅就会导致内存泄漏,往往我们会在页面的onDestroy方法中执行如下方法:

1
2
3
if(rxDisposable!=null && !rxDisposable.isDisposed()){
rxDisposable.dispose();
}

为了代码的冗余我们还会去封装工具类去统一的处理回收,但是无法避免的会手动调用多次,那么如何更优雅及方便的进行资源的回收呢?
答案是肯定有的,本文会介绍更优雅、更安全、更方便的去使用Rxjava无需担心资源回收的问题。

使用

下面介绍两种处理资源回收的第三方库Rxlifecycle、Autodispose

1.使用Rxlifecycle

该库让Rxjava可以基于第二个生命周期去处理未完成的订阅,避免内存泄漏

Github传送门

添加依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
implementation 'com.trello.rxlifecycle2:rxlifecycle:2.2.2'

// If you want to bind to Android-specific lifecycles
implementation 'com.trello.rxlifecycle2:rxlifecycle-android:2.2.2'

// If you want pre-written Activities and Fragments you can subclass as providers
implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.2'


// If you want to use Android Lifecycle for providers
implementation 'com.trello.rxlifecycle2:rxlifecycle-android-lifecycle:2.2.2'

// 如果使用kotlin
// If you want to use Kotlin syntax
implementation 'com.trello.rxlifecycle2:rxlifecycle-kotlin:2.2.2'

// If you want to use Kotlin syntax with Android Lifecycle
implementation 'com.trello.rxlifecycle2:rxlifecycle-android-lifecycle-kotlin:2.2.2'

该库提供RxAppCompatActivity、RxFragment、RxAppCompatDialogFragment、RxDialogFragment、RxFragmentActivity、RxActivity、RxDialogFragment、RxPreferenceFragment基类
方便使用者快捷使用,需要继承相应的基类就可以使用rxlifecycle管理Rxjava资源回收策略。

下面提供两种使用该库的两种使用方式:
案例都是继承与RxAppCompatActivity

1.bindToLifecycle()
在某个的生命周期发布订阅。则在对应生命周期取消订阅,如在onCreate里订阅,则在onDestroy取消订阅。在onResume里订阅,则在onStop取消订阅

案例:

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

public class RxLifecycleTestActivity extends RxAppCompatActivity {
private static final String TAG = RxLifecycleTestActivity.class.getSimpleName();
private Disposable dispose;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rxlifecycle_test);
dispose = Observable.interval(0, 1, TimeUnit.MILLISECONDS)
.doOnDispose(()->{
Log.e(TAG, "Unsubscribing subscription from onCreate()");
})
.compose(this.bindToLifecycle())
.subscribe(data -> {
Log.e(TAG, "onCreate: " + data.toString());
}, Throwable::printStackTrace);
}

@Override
protected void onDestroy() {
super.onDestroy();
if(dispose!=null){
Log.e(TAG, "onDestroy: Observable订阅是否关闭:" + dispose.isDisposed());
}
}
}

//控制台打印,在页面销毁时订阅已被关闭
2020-12-03 15:41:30.797 10772-10829/com.mi.qing.common.net E/RxLifecycleTestActivity: onCreate: 10919
2020-12-03 15:41:35.010 10772-10829/com.mi.qing.common.net E/RxLifecycleTestActivity: Unsubscribing subscription from onCreate()
2020-12-03 15:41:35.469 10772-10829/com.mi.qing.common.net E/RxLifecycleTestActivity: onDestroy: Observable订阅是否关闭:true

2.bindUntilEvent()
可指定生命周期取消订阅,如在onCreate里订阅,可指定在onStop里取消订阅。提供ActivityEvent类,其中的CREATE、START、 RESUME、PAUSE、STOP、 DESTROY分别对应生命周期内的方法。

案例:

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

public class RxLifecycleTestActivity extends RxAppCompatActivity {
private static final String TAG = RxLifecycleTestActivity.class.getSimpleName();
private Disposable dispose;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rxlifecycle_test);
dispose = Observable.interval(0, 1, TimeUnit.MILLISECONDS)
.doOnDispose(()->{
Log.e(TAG, "Unsubscribing subscription from onCreate()");
})
.compose(this.bindUntilEvent(ActivityEvent.STOP))
.subscribe(data -> {
Log.e(TAG, "onCreate: " + data.toString());
}, Throwable::printStackTrace);
}

@Override
protected void onPause() {
super.onPause();
if(dispose!=null){
Log.e(TAG, "onPause: Observable订阅是否关闭:" + dispose.isDisposed());
}
}

@Override
protected void onStop() {
super.onStop();
if(dispose!=null){
Log.e(TAG, "onStop: Observable订阅是否关闭:" + dispose.isDisposed());
}
}

@Override
protected void onDestroy() {
super.onDestroy();
if(dispose!=null){
Log.e(TAG, "onDestroy: Observable订阅是否关闭:" + dispose.isDisposed());
}
}
}

//控制台打印,在页面处于onStop生命周期时订阅已被关闭
2020-12-03 15:45:15.035 10772-10829/com.mi.qing.common.net E/RxLifecycleTestActivity: onCreate: 4464
2020-12-03 15:45:15.036 10772-10829/com.mi.qing.common.net E/RxLifecycleTestActivity: onPause: Observable订阅是否关闭:false
2020-12-03 15:45:15.037 10772-10829/com.mi.qing.common.net E/RxLifecycleTestActivity: Unsubscribing subscription from onCreate()
2020-12-03 15:45:15.038 10772-10829/com.mi.qing.common.net E/RxLifecycleTestActivity: onStop: Observable订阅是否关闭:true
2020-12-03 15:45:15.039 10772-10829/com.mi.qing.common.net E/RxLifecycleTestActivity: onDestroy: Observable订阅是否关闭:true

3.不继承该库自带的基类来使用
可以在需要使用的页面创建AndroidLifecycle.createLifecycleProvider(this),得到LifecycleProvider<Lifecycle.Event>返回类型进行使用
支持bindToLifecycle、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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
public class RxLifecycleTestActivity extends AppCompatActivity {
private static final String TAG = RxLifecycleTestActivity.class.getSimpleName();
private Disposable dispose;

private final LifecycleProvider<Lifecycle.Event> provider
= AndroidLifecycle.createLifecycleProvider(this);

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


dispose = Observable.interval(0, 1, TimeUnit.MILLISECONDS)
.doOnDispose(()->{
Log.e(TAG, "Unsubscribing subscription from onCreate()");
})
.compose(provider.bindToLifecycle())
.subscribe(data -> {
Log.e(TAG, "onCreate: " + data.toString());
}, Throwable::printStackTrace);

// dispose = Observable.interval(0, 1, TimeUnit.MILLISECONDS)
// .doOnDispose(()->{
// Log.e(TAG, "Unsubscribing subscription from onCreate()");
// })
// .compose(provider.bindUntilEvent(Lifecycle.Event.ON_STOP))
// .subscribe(data -> {
// Log.e(TAG, "onCreate: " + data.toString());
// }, Throwable::printStackTrace);
//
}

@Override
protected void onPause() {
super.onPause();
if(dispose!=null){
Log.e(TAG, "onPause: Observable订阅是否关闭:" + dispose.isDisposed());
}
}

@Override
protected void onStop() {
super.onStop();
if(dispose!=null){
Log.e(TAG, "onStop: Observable订阅是否关闭:" + dispose.isDisposed());
}
}

@Override
protected void onDestroy() {
super.onDestroy();
if(dispose!=null){
Log.e(TAG, "onDestroy: Observable订阅是否关闭:" + dispose.isDisposed());
}
}
}


//控制台打印,在页面处于onStop生命周期时订阅已被关闭
2020-12-03 15:50:35.326 10772-10829/com.mi.qing.common.net E/RxLifecycleTestActivity: onCreate: 6765
2020-12-03 15:50:35.327 10772-10829/com.mi.qing.common.net E/RxLifecycleTestActivity: onPause: Observable订阅是否关闭:false
2020-12-03 15:50:35.328 10772-10829/com.mi.qing.common.net E/RxLifecycleTestActivity: onStop: Observable订阅是否关闭:false
2020-12-03 15:50:35.329 10772-10829/com.mi.qing.common.net E/RxLifecycleTestActivity: Unsubscribing subscription from onCreate()
2020-12-03 15:50:35.330 10772-10829/com.mi.qing.common.net E/RxLifecycleTestActivity: onDestroy: Observable订阅是否关闭:true

2.使用Autodispose

该库用于自动绑定+处理RxJava流,借鉴Rxlifecycle开发,解决了Rxlifecycle的弊端,处理Rxjava流更加方便灵活。

Github传送门

添加依赖

1
2
implementation 'com.uber.autodispose:autodispose::1.4.0'
implementation 'com.uber.autodispose:autodispose-android-archcomponents:1.4.0'

AutoDispose比RxLifecycle好的地方在于它不需要你的Activity或Fragment继承指定的类。只要你的Activity或Fragment的父类实现了LifecycleOwner这个接口即可。通过源码发现,support.v7包中的AppCompatActivity最终继承自SupportActivity,SupportActivity实现了LifecycleOwner接口。support.v4包中的Fragment也实现了LifecycleOwner接口。AndroidX支持库同样也实现了LifecycleOwner接口,使用时只要能够获取到LifecycleOwner的地方就可以使用AutoDispose是不是非常方便。

下面介绍它的使用方式

1.AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(LifecycleOwner owner))

在某个的生命周期发布订阅。则在对应生命周期取消订阅,如在onCreate里订阅,则在onDestroy取消订阅。在onResume里订阅,则在onStop取消订阅

案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class RxLifecycleTestActivity extends AppCompatActivity {
private static final String TAG = RxLifecycleTestActivity.class.getSimpleName();
private Disposable dispose;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rxlifecycle_test);
dispose = Observable.interval(0, 1, TimeUnit.MILLISECONDS)
.doOnDispose(()->{
Log.e(TAG, "Unsubscribing subscription from onCreate()");
})
.as(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this)))
.subscribe(data -> {
Log.e(TAG, "onCreate: " + data.toString());
}, Throwable::printStackTrace);
}
}

2.AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(LifecycleOwner owner, Lifecycle.Event untilEvent))
可指定生命周期取消订阅,如在onCreate里订阅,可指定在onStop里取消订阅。提供ActivityEvent类,其中的CREATE、START、 RESUME、PAUSE、STOP、 DESTROY分别对应生命周期内的方法。

案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

public class RxLifecycleTestActivity extends AppCompatActivity {
private static final String TAG = RxLifecycleTestActivity.class.getSimpleName();
private Disposable dispose;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rxlifecycle_test);
dispose = Observable.interval(0, 1, TimeUnit.MILLISECONDS)
.doOnDispose(()->{
Log.e(TAG, "Unsubscribing subscription from onCreate()");
})
.as(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this, Lifecycle.Event.ON_STOP)))
.subscribe(data -> {
Log.e(TAG, "onCreate: " + data.toString());
}, Throwable::printStackTrace);
}
}

总结

两种框架的使用都能解决使用rxjava流的过程内存泄漏的问题,读者们按需使用。这种方式能够大大减少开发过程中的冗余代码及处理遗漏导致的内存泄漏,读者可自行封装
简便使用。

框架及Demo源码
源码地址 MiQingWang/CommonNetFrame

-------- 本文章已被掏空 学无止境下一章 --------