Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱
MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina.com

RxJava RxLifecycle 生命周期 内存泄漏 MD

Demo地址

GitHub


目录

简介

另一个功能与此库类似、核心设计借鉴此库、此库作者也参与设计、此库作者认为比此库好、但是星星比较少、国内不流行、上手比较难的库:https://github.com/uber/AutoDispose

添加依赖

implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.2'

完整依赖项:

implementation 'com.trello.rxlifecycle2:rxlifecycle:2.2.2' //基础库
implementation 'com.trello.rxlifecycle2:rxlifecycle-android:2.2.2' //Android中使用的库,内部引用了基础库,如果使用此库则无需再引用基础库
implementation 'com.trello.rxlifecycle2:rxlifecycle-components:2.2.2' //Android组件库,里面定义了例如RxActivity、RxFragment等Android组件,内部引用了基础库和Android库,如果使用此库则无需再重复引用
implementation 'com.trello.rxlifecycle2:rxlifecycle-components-preference:2.2.2' // Android使用的库,继承NaviActivity使用
implementation 'com.trello.rxlifecycle2:rxlifecycle-navi:2.2.2' //Android使用的库,继承LifecycleActivity使用,需要引入Google的仓库支持
implementation 'com.trello.rxlifecycle2:rxlifecycle-android-lifecycle:2.2.2' //使用AndroidLifecycle
implementation 'com.trello.rxlifecycle2:rxlifecycle-kotlin:2.2.2' // 支持Kotlin语法的RxLifecycle基础库
implementation 'com.trello.rxlifecycle2:rxlifecycle-android-lifecycle-kotlin:2.2.2' // 支持Kotlin语法的Android库

产生背景

随着 RxJava 及 RxAndroid 的逐渐推广,使用者越来越多,但是有一个问题,RxJava 的使用不当极有可能会导致内存泄漏,通常我们会有如下几种解决方案:

  • 解决方案1:手动为 RxJava 的每一次订阅进行控制,在指定的时机进行取消订阅。这种情况在订阅比较少的情况下没问题,但是如果非常多,没有意义的脏代码会让你写到吐。
  • 解决方案2:在 BaseActivity 中记录一个 List<Subscription> 或 List<Disposable>,每次使用后 add 进队列,在页面 onDestory 统一 unsubscribe() 或 dispose()。但是从一开始就发现这个方法实在是太搓了,脏代码并没有减少。
  • 解决方案3:后来发现很多人用一个类 CompositeSubscription,然而发现这个类仅仅是帮我们维护了一个 Set 而已,你妹,看起来高大上的样子,实际上屁都不是!

RxLifecycle 就是专门解决这一痛点的。一开始发现要让我们的 Activity 或 Fragment 继承自库中的类,就比较担心局限性,后来发现,这货这么做完全是为了帮我们省事呀,我们常用的一些比如 FragmentActivity、AppCompatActivity 等,基本都有相应的 Rx*** 类,实际使用时,我们只需将我们的 BaseActivity 改为实现它就行了。

该库允许基于另一个生命周期流[a second lifecycle stream]自动完成序列[automatically complete sequences]

此功能在Android中很有用,因为在Android中,不完整的订阅[incomplete subscriptions]可能导致内存泄漏。

注意

注意:【RxLifecycle 的原理是不是基于自动调用 unsubscribe 的】

RxLifecycle实际上并没有取消订阅[unsubscribe]序列。 相反,它终止[terminates]了序列。 它的表现方式因类型而异:

  • Observable、Flowable 和 Maybe:发出 onCompleted()
  • Single 和 Completable:发出onError(CancellationException)

如果序列需要 Subscription.unsubscribe() 行为,则建议您自己手动处理订阅并在适当时调用unsubscribe()。

使用方式 compose

您必须以表示生命周期流的 Observable <T> 开头。 然后使用 RxLifecycle 将序列绑定到该生命周期。

您可以在生命周期发出任何内容时进行绑定:

myObservable
.compose(RxLifecycle.bind(lifecycle))
.subscribe(...);
``` 或者您可以在特定生命周期事件发生时绑定:
```java
myObservable
.compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY))
.subscribe(...);
``` 或者,您可以让 RxLifecycle 确定结束序列的适当时间:
```java
myObservable
.compose(RxLifecycleAndroid.bindActivity(lifecycle))
.subscribe(...);
```
它假定您想要在相反的`[opposing]`生命周期事件中结束序列 - 例如,如果在 START 期间订阅,它将在 STOP 时终止。如果您在 PAUSE 之后订阅,它将在下一个销毁事件`[destruction event]`中终止,例如,PAUSE 将在 STOP 中终止。 # RxLifecycle
生命周期来自哪里? 通常,它们由适当的 `LifecycleProvider <T>` 提供。 但他们的实现`[implemented]`在哪里? 你有几个选择:
- 使用 rxlifecycle-components 中提供的 RxActivity,RxFragment 等类的子类
```java
public class MyActivity extends RxActivity {
@Override
public void onResume() {
super.onResume();
myObservable
.compose(bindToLifecycle()) //使用内置的 bindToLifecycle() 或 bindUntilEvent() 方法即可
.subscribe(...);
}
}
  • 使用 Navi + rxlifecycle-navi 生成:
public class MyActivity extends NaviActivity {
private final LifecycleProvider<ActivityEvent> provider = NaviLifecycle.createActivityLifecycleProvider(this);
@Override
public void onResume() {
super.onResume();
myObservable
.compose(provider.bindToLifecycle())
.subscribe();
}
}
  • 使用 Android 的 lifecycle + rxlifecycle-android-lifecycle 生成
public class MyActivity extends LifecycleActivity {
private final LifecycleProvider<Lifecycle.Event> provider = AndroidLifecycle.createLifecycleProvider(this);
@Override
public void onResume() {
super.onResume();
myObservable
.compose(provider.bindToLifecycle())
.subscribe();
}
}
  • 自己编写实现

案例

public class RxBindingActivity extends RxFragmentActivity {
private Button btn;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rxbinding); btn = findViewById(R.id.btn);
RxView.clicks(btn) //点击获取验证码
.doOnNext(o -> btn.setEnabled(false))
.subscribe(o -> Observable.interval(1, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
.take(10)
.compose(bindToLifecycle()) //绑定生命周期
.subscribe(aLong -> btn.setText(10 - aLong + " 秒"),
Throwable::printStackTrace,
() -> {
btn.setEnabled(true);
btn.setText("重新获取");
}));
} @Override
protected void onResume() {
super.onResume();
RxView.clicks(btn)
.buffer(1000, TimeUnit.MILLISECONDS, 5) //效果仅仅是,每隔1秒钟收集一下此1秒钟内的点击次数
.compose(bindUntilEvent(ActivityEvent.STOP))//在 onStop 时取消
.subscribe(list -> Log.i("【bqt】", "一秒钟内的点击次数:" + list.size()));
}
}

2018-9-15

RxJava RxLifecycle 生命周期 内存泄漏 MD的更多相关文章

  1. C语言基础 (10) 变量作用域,生命周期 内存结构

    01 课程回顾 1.指针数组 注意: 对于数组来说,在使用sizeof的时候a和&a[0]是不一样的, 虽然以%x打印出来他们都是地址 2.值传递 int a; fun(a); int *** ...

  2. LeakCanary检测内存泄漏.md

    一使用步骤 添加依赖 // 内存泄漏检测 debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.4' releaseCompile ...

  3. Android性能优化之利用Rxlifecycle解决RxJava内存泄漏

    前言: 其实RxJava引起的内存泄漏是我无意中发现了,本来是想了解Retrofit与RxJava相结合中是如何通过适配器模式解决的,结果却发现了RxJava是会引起内存泄漏的,所有想着查找一下资料学 ...

  4. AutoDispose代替RxLifecycle优雅的解决RxJava内存泄漏问题

    使用过Rxjava的小伙伴都知道,在使用RxJava时如果处理不当,很可能会产生内存泄漏的问题. 我们使用rxjava最大的原因是响应式编程使我们的异步操作代码变得很优雅,在Android中,也使线程 ...

  5. RxJava 和 RxAndroid 三(生命周期控制和内存优化)

    rxjava rxandroid 赵彦军 前言:对Rxjava.Rxandroid不了解的同学可以先看看 RxJava 和 RxAndroid RxJava 和 RxAndroid 二(操作符的使用) ...

  6. RxJava 和 RxAndroid (生命周期控制和内存优化)

    RxJava使我们很方便的使用链式编程,代码看起来既简洁又优雅.但是RxJava使用起来也是有副作用的,使用越来越多的订阅,内存开销也会变得很大,稍不留神就会出现内存溢出的情况,这篇文章就是介绍Rxj ...

  7. autofac生命周期入门(如何避免内存泄漏)

    如果你是一个IOC新手,那么生命周期可能会比较难以理解.以至于谈到这个问题时,一些老手也时常表示疑虑和害怕.一个令人不安的问题就是-对象没有在合适的时机被销毁.这样一来内存的使用率就会一直攀升,直到程 ...

  8. JVM的内存管理、对象的生命周期、内存泄漏

    1 JVM内存 分为“堆”.“栈”和“方法区”三个区域,分别用于存储不同的数据 1.1 堆 JVM在其内存空间开辟一个称为”堆”的存储空间,这部分空间用于存储使用new关键字所创建的对象. 1.2 栈 ...

  9. LeakCanary 内存泄漏 监测 性能优化 简介 原理 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

随机推荐

  1. BZOJ2655 calc

    拉格朗日插值+dp 直接dp是n立方的,我们考虑优化. dp式子为f[i][j]=f[i-1][j-1]*j*i+f[i-1][j]表示i个元素选j个的答案 然后发现最高次就是2j次,所以我们预处理出 ...

  2. BZOJ4205 : 卡牌配对

    对于两张卡牌,如果存在两种属性值不互质,则可以匹配. 只考虑200以内的质数,一共有46个,可以新建3*46*46个点来表示一类属性值中有这两种质数的卡牌. 然后对于每张卡牌,枚举它的质因子,最多只有 ...

  3. 外键的约束(Mysql、PostgreSQL)

    关于外键是什么,具体不再详述,可以自行百度. 讲一下关于外键的 On Delete和On Update的使用 最近在项目的表中看到这些,不懂顺便查了查: ONSTRAINT "c_clust ...

  4. nuxus 3在Maven项目的配置和POM文件的配置

    在nuxus 3中的Maven默认会创建三个仓库,这三个仓库的关系如下: public是release和snapshot的全集,release默认为关闭状态,所以在配置nexus 3时需要将其开启. ...

  5. HDU 4763 Theme Section (2013长春网络赛1005,KMP)

    Theme Section Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  6. STM32F4XX devices vector table for EWARM toolchain.

    ;/******************** (C) COPYRIGHT 2015 STMicroelectronics ******************** ;* File Name : sta ...

  7. 《Go学习笔记 . 雨痕》类型

    一.基本类型 清晰完备的预定义基础类型,使得开发跨平台应用时无须过多考虑符合和长度差异. 类型 长度 默认值 说明 bool 1 false   byte 1 0 uint8 int, uint 4, ...

  8. 推荐一个文献翻译软件--Deja Vu X

    首先我的这篇博客推荐的软件并非你觉得翻译精确度有多高的软件,假设是这种话就不用往下看了,免得浪费时间,仅仅是一个对于翻译文献非常方便的工具,方面在哪请看下文. 我是不会告诉你凡事用过这个软件的人都说好 ...

  9. .NET基于Eleasticsearch搭建日志系统实战演练

    一.需求背景介绍 1.1.需求描述 大家都知道C/S架构模式的客户端应用程序(比如:WinForm桌面应用.WPF.移动App应用程序.控制台应用程序.Windows服务等等)的日志记录都存储在本地客 ...

  10. 在ASP.NET MVC中使用typeahead.js支持预先输入,即智能提示

    使用typeahead.js可以实现预先输入,即智能提示,本篇在ASP.NET MVC下实现.实现效果如下: 首先是有关城市的模型. public class City { public int Id ...