“好雨知时节,当春乃发生”的ActiveData
一、前言
1、在鸿蒙系统之Lifecycle感知宿主的生命周期这篇文章中,我们介绍了Lifecycle
,如果你还不熟悉Lifecycle
,建议你先去看下。本文介绍的是“好雨知时节,当春乃发生”的ActiveData
。
2、ActiveData
是鸿蒙系统上的一款消息订阅和分发组件,简单的说就是,ActiveData
可以发送数据给观察者,观察者可以接收到ActiveData
发送过来的数据。
3、ActiveData
的消息分发机制,是EventHandler
所不能比拟的。EventHandler
在发送消息的时候,不会顾及当前页面是否可见,有消息就发,这样就可能导致应用在后台或者页面不可见时,仍然做一些无用的工作,从而导致内存泄漏。EventHandler
在发消息的时候,那是“各人自扫门前雪,莫管他人瓦上霜”。
4、ActiveData
会利用Lifecycle
来感知宿主的生命周期,默认情况下,只有当宿主处在活跃状态时,也就是宿主执行了onActive
方法后,ActiveData
才会把数据发送给观察者。当宿主被销毁的时候,也就是宿主执行了onStop
方法后,ActiveData
会自动的将观察者给移除掉。用“好雨知时节,当春乃发生”来形容ActiveData
最好不过了,好雨知道下雨的节气,正是在春天植物萌发生长的时候。ActiveData
知道发送数据给观察者的时候正是宿主活跃的时候,宿主销毁的时候正是移除观察者的时候。
二、ActiveData
ActiveData
主要有四个方法
addObserver(DataObserver<T> observer, boolean always)
参数名称 | 参数含义 |
---|---|
observer | 要添加的观察者,该参数不能为空 |
always | 表示是否在任何生命周期状态下发送数据更改通知。值true表示在任何生命周期状态下发送通知。值false表示仅当对象处于前台(活动状态)时才发送通知。 |
-
removeObserver(DataObserver<T> observer)
移除指定的观察者
参数名称 | 参数含义 |
---|---|
observer | 要移除的观察者 |
-
setData(T value)
发送数据给观察者
参数名称 | 参数含义 |
---|---|
value | 发送给观察者的数据 |
-
T getData()
获取发送的数据
三、DataObserver
DataObserver
是一个抽象类,它就是观察者,ActiveData
就是将数据发送给DataObserver
。DataObserver
有两个方法。
-
onChanged(T value)
通知观察者正在观察的数据已更改,观察者必须实现此方法,以便在数据更改时通知他们。
参数名称 | 参数含义 |
---|---|
value | activedata发送给观察者的数据 |
-
setLifecycle(Lifecycle owner)
设置观察者的生命周期,方法的参数是Lifecycle
,如果不熟悉Lifecycle
,可以查看鸿蒙系统之Lifecycle感知宿主的生命周期
参数名称 | 参数含义 |
---|---|
Lifecycle | 观察者的生命周期,其实就是宿主的生命周期 |
四、ActiveData的具体用法
在下面的代码中,我们创建了一个DataObserver
对象,在onStart
方法里面创建ActiveData
对象,泛型为string
,这也就意味着,ActiveData
发送一个字符串给观察者。调用ActiveData
的setData
方法发送数据,调用DataObserver
的setLifecycle
方法来给观察者设置生命周期,这里直接调用宿主的getLifecycle
方法,给ActiveData
添加观察者,第二个参数false
,这就意味着,只有当宿主处在活跃状态的时候,观察者才会接收到数据。
public class MainAbility extends Ability {
private DataObserver<String> mDataObserver = new DataObserver<String>() {
/**
* 接收ActiveData发送过来的数据
*
* @param s
*/
@Override
public void onChanged(String s) {
LogUtils.info("yunfei", s);
}
};
@Override
public void onStart(Intent intent) {
super.onStart(intent);
super.setMainRoute(MainAbilitySlice.class.getName());
// 创建ActiveData对象,泛型为string,这也就意味着,ActiveData发送一个字符串给观察者
ActiveData<String> activeData = new ActiveData<>();
// 发送数据
activeData.setData("更新页面");
// 给观察者设置生命周期,直接调用宿主的getLifecycle()方法
mDataObserver.setLifecycle(getLifecycle());
// 添加观察者,第二个参数false,这就意味着,只有当宿主处在活跃状态的时候,activeData才把数据发送给观察者
activeData.addObserver(mDataObserver, false);
LogUtils.info("yunfei", "onStart");
}
@Override
protected void onActive() {
super.onActive();
LogUtils.info("yunfei", "onActive");
}
}
代码运行起来后,我们会发现,虽然我们在onStart
方法里面给观察者发送了数据,但是观察者却是在onActive
方法执行完成之后,才接收到了数据,这是因为我们在调用activeData
的addObserver
方法时,将第二个参数设置为false,这样只有当宿主处在活跃状态的时候,activeData才把数据发送给观察者。
如果多次调用
ActiveData
的setData
方法,也就是多次的发送数据,观察者只会接收到最新的那条数据,也就是最后一次调用setData
方法发送的数据。
五、ActiveData的优缺点
5、1 优点
- 不会造成内存泄漏,当宿主销毁的时候,
ActiveData
会自动移除观察者。 - 不会在成崩溃,当宿主销毁的时候,观察者收不到消息。
- 页面上的数据永远是最新的,如果多次发送消息,观察者只能收到最新的数据。
- 不需要手动处理生命周期,开发者不需要在宿主的
onStop
方法里面移除观察者。
5、2 缺点
-
ActiveData
默认支持粘性事件,多个观察者会收到同一条消息,这在一定程度上会给我们带来麻烦。比如,发送登录事件,登录完成后,又来了一个观察者,新的观察者也能收到登录事件,此时又会进行登录。 -
ActiveData
不支持跨进程发送消息。这个也不能完全算是缺点,毕竟,相对而言,大部分的应用并不需要跨进程发送消息。
最后,我基于ActiveData
实现了一款事件总线框架,有兴趣的读者可以阅读鸿蒙系统事件总线框架—好雨这篇文章。