开始
最近在写鸿蒙项目发现页面与页面刷新数据不好使,提了工单说要我们要用AppStorage,当时懵了,到时候项目岂不是到处是AppStorage?官方是这么解释的AppStorage的
- AppStorage:应用全局的UI状态存储
- AppStorage是应用全局的UI状态存储,是和应用的进程绑定的,由UI框架在应用程序启动时创建,为应用程序UI状态属性提供中央存储。
- 和AppStorage不同的是,LocalStorage是页面级的,通常应用于页面内的数据共享。而AppStorage是应用级的全局状态共享,还相当于整个应用的“中枢”,持久化数据PersistentStorage和环境变量Environment都是通过和AppStorage中转,才可以和UI交互。
但是官方也是不建议用AppStorage的,看看他怎么解释的
- 不建议开发者使用@StorageLink和AppStorage的双向同步的机制来实现事件通知,AppStorage是和UI相关的数据存储,改变会带来UI的刷新,相对于一般的事件通知,UI刷新的成本较大。
下面来详解下liveeventbus的使用流程
效果图
开发环境
-
Windows
-
DevEco Studio NEXT Developer Preview2
-
HarmonyOS next Developer Preview2
-
java version "11.0.18" 2023-01-17 LTS
-
hdc 1.2.0a
-
手机:Mate 60Pro (HarmonyOS NEXT Developer Preview2)
导入liveeventbus库
"@ohos/liveeventbus": "^2.1.0"
封装工具类
- 先new一下Lifecycle,注意:这里api9和api11写法不一样,因为api11加了很多约束
private mLifecycle: Lifecycle = new Lifecycle(MState.CREATED) //11写法
private mLifecycle: Lifecycle //9写法
- 接下来订阅/获取消息,这里我们用泛型,因为收到的消息可能是任意类型数据
/**
* 订阅/获取消息
* @param event
*/
getLiveEvent<T>(event: string, callBack: (isEvent: T) => void = () => {
}) {
//创建生命周期感知对象
this.mLifecycle = new Lifecycle(MState.STARTED)
//订阅消息
LiveEventBus
.get<T>(event)
.observe(this, {
onChanged(b: T) {
if (b) {
callBack(b)
}
}
});
}
- 发送消息,同上也用泛型,因为发送可以是任意类型数据
/**
* 发送消息
* @param event
* @param params
*/
sendLiveEvent<T>(event: string, params?: T | boolean) {
if (params === undefined) {
params = true; // 给 params 赋默认值
}
//发送消息
LiveEventBus.get<T>(event).post(params as T);
}
- 销毁消息
/**
* 销毁消息
*/
destroyedLiveEvent() {
this.mLifecycle.markState(MState.DESTROYED)
}
- 生命周期感知对象
getLifecycle(): Lifecycle {
return this.mLifecycle
}
- 最后导出供业务层使用
let liveEventUtils = new LiveEventUtils()
export default liveEventUtils as LiveEventUtils;
使用
- 因为消息会比较多,建议定义常量来进行区分
static readonly REFRESH_HOME_DATA = "refresh_home_data";
- 为了测试发送event实体,建议单独定义一个包存event,我们定义一个event类
export interface TestEvent {
event: string
}
export class TestEventModel implements TestEvent {
event: string = ''
constructor(model: TestEvent) {
this.event = model.event
}
}
- 发送消息(默认消息和实体消息)
liveEventUtils.sendLiveEvent<boolean>(LiveEventConstant.REFRESH_HOME_DATA) //发送默认为true
liveEventUtils.sendLiveEvent<TestEvent>(LiveEventConstant.REFRESH_HOME_DATA, new TestEventModel({
test: '测试'
})) //发送消息实体
- 接收消息
//收到默认消息
liveEventUtils.getLiveEvent(LiveEventConstant.REFRESH_HOME_DATA, (isEvent: boolean) => {
if (isEvent) {
AlertDialog.show({ message: '收到消息了' + JSON.stringify(isEvent) })
}
})
//收到实体消息
liveEventUtils.getLiveEvent(LiveEventConstant.REFRESH_HOME_DATA, (event: TestEvent) => {
if (event) {
AlertDialog.show({ message: '收到消息了' + JSON.stringify(event.title) })
}
})
核心代码分析
其实原理很简单,就是利用创建生命周期感知对象,然后用observe来进行消息更新,跟安卓的LiveData、Lifecycle实现原理一样,底层是观察者模式
- 看看这块代码是不是很熟悉?没错,就是MutableLiveData,其实安卓这块的liveData也是这样写的
class MutableLiveData<T> extends LiveData<T> {
/**
* Sets current LiveData value, and notifies observers.
*
* @param value The value to set.
*/
public postValue(value: T) {
this.data = value
this.observers.forEach(observer => {
observer.onChanged(value)
})
}
}
export default MutableLiveData
- 然后用了一个LiveData用来观察更新
abstract class LiveData<T> {
protected observers: Array<Observer<T>> = []
protected data: T | null = null
/**
* Observes changes in LiveData value. If value set before observed, immediately invokes observer.
*
* @param observer The observer to watch for changes.
*/
public observe(observer: Observer<T>) {
this.observers.push(observer)
const tData = this.data
if (tData != null) observer.onChanged(tData)
}
/**
* @return The current LiveData value.
*/
public getValue(): T | null {
return this.data
}
/**
* Attempts to remove observer.
*
* @param observer The observer to remove.
*
* @return True if removed otherwise false.
*/
public removeObserver(observer: Observer<T>): Boolean {
const index = this.observers.indexOf(observer)
if (index != -1) {
this.observers.splice(index, 1)
return true
}
return false
}
/**
* Removes all observers.
*/
public removeAllObservers() {
this.observers.splice(0, this.observers.length)
}
/**
* @return A read-only version of observers.
* Mostly used for testing.
*/
getObservers(): ReadonlyArray<Observer<T>> {
return this.observers
}
}
- 接下来Observer接口有个onChanged方法,这个方法其实才是核心
interface Observer<T> {
/**
* Called when the data is changed.
* @param t The new data
*/
onChanged(t:T):void;
}
-
好了,就到这了,祝大家周末愉快!
下集预告
下一篇我们来写一个首页渐变
本文正在参加华为鸿蒙有奖征文征文活动