华为仓颉鸿蒙HarmonyOS NEXT原生UI状态管理(类似SwiftUI和Flutter的状态管理)
本文篇幅较长,建议点赞收藏,以免找不到哟(^U^)ノ~YO
Flutter的状态管理:
setState()方法:Flutter中最简单的状态管理方式是使用setState()方法来通知Flutter框架重新构建UI以反映新的状态。
Provider:Provider是Flutter社区广泛使用的状态管理库,它提供了一种简单而有效的方式来管理应用的状态,并支持依赖注入和消费者模式。
Bloc:Bloc是一种基于事件驱动的状态管理库,它有助于将业务逻辑与UI分离,并使状态管理更加结构化。
GetX:GetX是另一个轻量级且高性能的状态管理工具,它提供了便捷的方式来管理状态、路由和依赖注入。
SwiftUI的状态管理:
@State和@Binding:SwiftUI通过@State和@Binding属性包装器来管理界面组件的状态,并实现UI的响应式更新。
ObservableObject和@ObservedObject:SwiftUI还支持ObservableObject协议和@ObservedObject属性包装器,用于管理应用的全局状态和数据流。
Combine:SwiftUI结合了Combine框架,可以使用Publishers和Subscribers来处理数据流和响应式编程。
Redux:虽然不是官方支持的方式,但在SwiftUI中也可以使用Redux架构来管理复杂的状态
仓颉的状态管理具体如下:
@Entry
@Entry 用于指明当前页面的入口组件,仅能装饰在被 @Component 修饰的子组件上。一个文件最多只能有一个 @Entry
示例
@Entry
@Component
class ParentComponent {
func build() {
Column {
Text("")
}
}
}
@Component
@Component 用于修饰可重用的 UI 单元,该单元必须为 Class 类型。被修饰的class能够成为一个单独的组件,也被称为自定义组件。在render函数中描述UI结构。
- 自定义组件中的成员变量必须声明类型
- 自定义组件必须实现render函数
- 自定义组件禁止自定义构造函数
- 自定义组件禁止继承
- 自定义组件禁止使用泛型
示例:
@Component
class ParentComponent {
func build() {
Column {
Text("")
}
}
}
自定义组件可以在其他组件中使用
@Component
class SubComponent {
func build() {
Column {
Text("")
}
}
}
@Component
class ParentComponent {
func build() {
Column {
Text("")
SubComponent()
}
}
}
如果类中有成员变量,可以通过命名参数传值。其中,对于没有初始值的成员变量,必须在创建实例的时候传值( @Consume 装饰的变量除外),有初始值的则可以选择性地传值;对于let修饰的且带有初始值的成员变量,则不可在创建实例的时候传值。
@Component
class SubComponent {
@Link var cnt: Int64
let innerCnt = 0
var count: Int64 = 0
func build() {
Column {
Text("")
}
}
}
@Component
class ParentComponent {
@State var cnt: Int64 = 0
func build() {
Column {
Text("")
SubComponent() // Error cnt没有初始化
SubComponent(cnt: cnt) // OK count有初始值,可以不传值
SubComponent(cnt: cnt, innerCnt: cnt) // Error innerCnt不可通过构造传值
}
}
}
@State
@State 修饰的变量是组件内部的状态数据,当这些状态数据被修改时,将会调用所在组件的render刷新。
被 @State 修饰的成员变量必须指明类型和初始值。由于状态是需要被更改的数据,所以对于被 @State 修饰的变量必须通过 var 来声明,不能使用 let。
- 支持多种类型:支持基础数据类型:char、UInt8/16/32/64、Int8/16/32/64、Float16/32/64、Bool、String、Enum、Struct等;支持类类型和数组类型,但是如果要感知内部的变化,对于类类型,在定义的时候需要被@Observed修饰(详见@Observed和@Publish一节);对于数组类型则需要使用ObservedArray
和ObservedArrayList ,详见ObservedArray和ObservedArrayList一节。 - 私有:仅在组件内访问;不可被 public protected 等修饰符修饰;
- 支持多个实例:一个组件中可以定义多个标有 @State的属性;
- 需要本地初始化:必须为所有 @State 变量分配初始值。
- 创建自定义组件时支持通过状态变量名设置初始值:在创建组件实例时,可以通过变量名显式指定 @State状态属性的初始值。
示例
@Entry
@Component
class ParentComponent {
@State var count: ObservedArrayList<T> = 0
func build() {
Column {
Button("This is a case of @State ${count}")
.onClick({evt =>
count[0] = 9
})
}
}
}
@Link
@Link 与 @State 有相同的语义,但初始化方式不同。 @Link 装饰的变量必须使用其父组件提供的变量进行初始化,被 @Link 修饰的成员变量必须指明类型,且只能使用 var 来声明。允许组件内部修改 @Link 变量,且更改会通知给父组件,即 @Link 属于双向数据绑定。 @Link 修饰当前组件所拥有的状态,仅可在子组件中定义。
- 支持多种类型: @Link 变量的值与 @State 变量的类型相同。
- 私有:仅在组件内访问;不可被 public protected 等修饰符修饰;
- 支持多个实例:一个组件中可以定义多个标有 @Link 的属性;
- 双向通信:子组件对 @Link 变量的更改将同步修改父组件的 @State 变量;
示例
@Component
class SubSubComponent {
@Link var count: Int64
var commonCount: Int64 = 0
func build() {
Column {
Button("This is a case of @Link ${count} _____ SubSubComponent ${commonCount}").onClick({evt =>
count = count + 1
})
}
}
}
@Component
class SubComponent {
@Link var count: Int64
func build() {
Column {
Button("This is a case of @Link ${count} _____ SubComponent")
.onClick({evt =>
count = count + 1
})
SubSubComponent(count: count, commonCount: count)
}
}
}
@Entry
@Component
class ParentComponent {
@State var count: Int64 = 0
func build() {
Column {
Button("This is a case of @Link ${count} _____ ParentComponent")
.onClick({evt =>
count = count + 1
})
SubComponent(count: count)
}
}
}
@Prop
@Prop 与 @State 有相同的语义,但初始化方式不同。 @Prop 装饰的变量必须使用其父组件提供的变量进行初始化,被 @Prop 修饰的成员变量必须指明类型,且只能使用 var 来声明。允许组件内部修改 @Prop 变量,但更改不会通知给父组件,即 @Prop 属于单向数据绑定。 @Prop 修饰当前组件所拥有的状态,仅可在子组件中定义。
@Prop 状态数据具有以下特征:
- 支持类型: @Prop 变量的值与 @State 变量的类型相同。
- 私有:仅在组件内访问;不可被 public protected 等修饰符修饰;
- 支持多个实例:一个组件中可以定义多个标有 @Prop 的属性;
- 创建自定义组件时将值传递给@Prop变量进行初始化:在创建组件的新实例时,必须初始化所有 @Prop 变量,不支持在组件内部进行初始化。
示例
@Component
class SubComponent {
@Prop var count: Int64
func build() {
Column {
Button("This is a case of @Prop ${count} _____ SubComponent")
.onClick({evt =>
count = count + 1
})
}
}
}
@Entry
@Component
class ParentComponent {
@State var count: Int64 = 0
func build() {
Column {
Button("This is a case of @Prop ${count} _____ ParentComponent")
.onClick({evt =>
count = count + 1
})
SubComponent(count: count)
}
}
}
@Observed and @Publish
针对类类型的状态变量,引入 @Observed 和 @Publish。
- @Observed 修饰类,被修饰的类表示可以被观察到。需要和 @Publish 一起使用。没有被 @Publish 修饰的属性,变化了也不会触发UI更新。 @Observed 的类中不能定义init函数。
- @Publish 修饰属性,被修饰的属性能够被观察到,一旦属性发生变化,会自动修改页面。 @Publish 只能在 @Observed 修饰的类中使用。可以给属性赋初值,如果没有赋值,需要在构造时给值。
- @Publish 修饰的变量只能由var声明。
注意
被 @Publish 修饰的成员变量必须指明类型和初始值。但对于String,Int64,Float64和Bool类型,如果变量的初始值是上述类型的字面量,则可以省略类型。
示例
@Observed
class Book {
@Publish var title: String = ""
@Publish var price: Int64 = 9
var id: Int64
}
@Component
class Demo {
@State var book: Book = Book(title: "myBook", id: 3214324)
func build() {
Column {
Text("${book.title}, ${book.price}")
Button("click").onClick({e =>
book.title = "noBook"
})
}
}
}
多层嵌套类
如果类中的属性也是类类型,且该属性需要被监听,那么这个类也要被@Observed修饰
@Observed
class Directory {
@Publish var title: String = ""
@Publish var price: Int64 = 9
}
@Observed
class Book {
@Publish var dir: Directory = Directory()
@Publish var title: String = ""
@Publish var price: Int64 = 9
var id: Int64
}
@Component
class Demo {
@State var book: Book = Book(title: "myBook", id: 3214324)
func build() {
Column {
Text("${book.title}, ${book.price}")
Button("click").onClick({e =>
book.title = "noBook"
})
}
}
}
@Provide and @Consume
@Provide 作为数据的提供方,可以更新其子孙节点的数据,并触发页面渲染。 @Consume 在感知到 @Provide 数据的更新后,会触发当前view的重新渲染。
同样地, @Consume 发生变化后,也会触发 @Provide 所在的页面渲染,二者构成双向数据绑定。
- 支持类型: @Provide 和 @Consume 变量的值与 @State 变量的类型相同。
- 相互关联的 @Provide 和 @Consume 的变量名和类型必须相同,
- @Provide 和 @Consume 修饰当前组件所拥有的状态,仅在当前组件内生效,且只可以用于修饰当前子组件的成员变量,不可被 public protected 等修饰符修饰;
- @Provide 修饰的成员变量必须指明类型且有初始值,变量只能由var声明。
- @Consume 修饰的成员变量必须指明类型且不能有初始值,变量只能由var声明。
- 与 @Link 和 @Prop 不同的是, @Consume 的值不需要通过构造函数传递。只要保证 @Provide 和 @Consume 的类型和变量名一致,且 @Consume 声明的变量所在的组件是 @Provide 声明的变量所在的组件的子孙组件,就可以建立 @Provide 和 @Consume 之间的双向数据绑定。
如果只有 @Provide ,没有 @Consume,则该 @Provide可视作 @State。而 @Consume必须有对应的 @Provide,如果其父辈节点中没有相对应的 @Provide变量,则该@Consume变量定义所在的自定义组件将不会显示,且会在log中打印runtime报错。
示例
@Component
class SubSubComponent {
@Consume var stateContent: Int64
func build() {
Column {
Text("this is SubSubComponent ${this.stateContent}")
Button("${this.stateContent}").onClick({evt => this.stateContent += 1})
}
}
}
@Component
class SubComponent {
func build() {
Column {
Text("this is SubComponent")
SubSubComponent()
}
}
}
@Entry
@Component
class ParentComponent {
@Provide var stateContent: Int64 = 0
func build() {
Column {
SubComponent()
Button("${this.stateContent}").onClick({evt => this.stateContent += 1})
}
}
}
@Builder
@Builder 装饰的方法用于定义组件的声明式UI描述,在一个自定义组件内快速生成多个布局内容。 @Builder 装饰方法的功能和语法规范与render函数相同。
- 支持泛型参数、泛型约束、命名参数、命名参数默认值等仓颉函数基本功能;
- 可以修饰全局函数,也可以修饰类的成员函数;
- 不支持使用 open 修饰并被重写(我们建议 @Builder 函数只定义在全局或 @Component 修饰的类中);
- 不支持使用 static 修饰作为类的静态方法;
- 函数的返回值类型为 Unit,返回值类型可以省略;
- 函数体中只允许包含 UI 组件声明(UI 组件声明包括:内置组件、@Component 修饰类的实例构造、@Builder 修饰函数的调用);
- 可以使用导出普通仓颉函数同样的策略,导出 @Builder 修饰的函数。
示例
@Builder
func f(fontSz: Int64, color: Color) {
Text("hello world").fontSize(fontSz).fontColor(color)
}
@Entry
@Component
class MyView {
func build() {
Column(20) {
f(20, Color.BLUE)
}
}
}
@BuilderParam
@BuilderParam 用来装饰指向@Builder方法的变量,开发者可在初始化自定义组件时对此属性进行赋值,为自定义组件增加特定的功能。
- 所修饰变量的类型为函数类型,且返回值类型为 Unit;
- 所修饰的变量声明中,变量的类型需要显示标注;
- 只能修饰类的成员变量声明,禁止修饰全局变量(否则将产生编译错误);
- 所修饰的类成员变量遵循 private 修饰符的可见性(即:只允许在类内部使用);
- 所修饰变量可以是可变的,也可以是不可变的,变量的可变性遵循仓颉语法由 let/var 关键字标识。
示例
@Entry
@Component
class MyView {
@Builder
func f1(): Unit {
f<Int64>(100, 30, color: Color.BLACK)
}
@Builder
func f2(): Unit {
f<String>("hello", 30, color: Color.RED)
}
func build() {
Column(10) {
FrameView(ab: f1, color: Color.GREEN)
FrameView(ab: f2, color: Color.GRAY)
}
}
}
@Component
class FrameView {
@BuilderParam let ab: () -> Unit
let color: Color
func build() {
Column(10) {
ab()
}.backgroundColor(color)
}
}
@Builder
func f<T>(label: T, fontSz: Int64, color!: Color = Color.WHITE): Unit where T <: ToString {
Text("${label}").fontSize(fontSz).fontColor(color)
}
@Watch
@Watch 用于监听状态变量的变化。如下给状态变量增加一个@Watch装饰器,通过@Watch注册一个回调方法onChanged,当状态变量count被改变时,触发onChanged回调。
- 可以监听 @State 、 @Prop 、 @Link 、 @Provide 、 @Consume 、 @StorageLink 和 @StorageProp 装饰的变量的变化。
- 被监听的变量必须声明类型。
示例
@Component
class MyView {
@State @Watch[onChanged] count: Int64 = 0
func onChanged() {}
func build() {...}
}
其中,onChanged函数是一个参数为空,且返回为空的函数。
ObservedArray and ObservedArrayList
提供ObservedArray和ObservedArrayList作为状态管理的数组类型,当其中数组发生变化时,如修改其中一项的值,删除或添加一项,就会触发UI更新。
ObservedArray
定义了状态管理的一个数组类型。
init(Array
public init(initValue: Array<T>)
状态管理数组的构造函数。
| 参数名 | 参数类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| initValue | Array |
是 | - | 状态管理数组的初始化数组。 |
subscribeInner(Observer)
public func subscribeInner(observer: Observer): Unit
对状态管理数组的每一项进行递归的观察绑定。
| 参数名 | 参数类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| observer | Observer | 是 | - | 绑定的观察类。 |
unsubscribeInner(oObserver)
public func unsubscribeInner(observer: Observer): Unit
对状态管理数组的每一项进行递归的解绑。
| 参数名 | 参数类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| observer | Observer | 是 | - | 解绑的观察类。 |
get()
public func get(): Array<T>
获取状态管理数组。
set(Array
public func set(newValue: Array<T>): Unit
设置状态管理数组。
| 参数名 | 参数类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| newValue | Array |
是 | - | 状态管理数组被设置的新数组值。 |
set(ObservedComplexAbstract)
public func set(newValue: ObservedComplexAbstract): Unit
设置状态管理数组。
| 参数名 | 参数类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| newValue | ObservedComplexAbstract | 是 | - | 状态管理数组被设置的新值。 |
public operator func [](index: Int64): T
读取数组中指定索引对应的数组项。
| 参数名 | 参数类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| index | Int64 | 是 | - | 指定读取数组项的索引。 |
[](Int64, T)
public operator func [](index: Int64, value!: T): Unit
改变数组中指定索引对应的数组项的值。
| 参数名 | 参数类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| index | Int64 | 是 | - | 指定数组项的索引。 |
| value | T | 是 | - | 指定索引对应的数组项的新值。 |
size
public prop size: Int64
获取状态管理数组的大小。
ObservedArrayList
提供支持状态管理的可变长度的数组的功能,可以感知内部的变化。
构造函数
init(ArrayList
public init(initValue: ArrayList<T>)
构造一个包含指定ArrayList数组中所有元素的 ObservedArrayList。
| 参数名 | 参数类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| initValue | ArrayList |
是 | - | ArrayList数组,用来初始化ObservedArrayList。 |
init(initValue: Array
public init(initValue: Array<T>)
构造一个包含指定Array数组中所有元素的 ObservedArrayList。
| 参数名 | 参数类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| initValue | Array |
是 | - | Array数组,用来初始化ObservedArrayList。 |
函数
subscribeInner(Observer)
public func subscribeInner(observer: Observer): Unit
对状态管理数组的每一项进行递归的观察绑定。
| 参数名 | 参数类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| observer | Observer | 是 | - | 绑定的观察类。 |
unsubscribeInner(Observer)
public func unsubscribeInner(observer: Observer): Unit
对状态管理数组的每一项进行递归的解绑。
| 参数名 | 参数类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| observer | Observer | 是 | - | 解绑的观察类。 |
get()
public func get(): ArrayList<T>
返回一个ArrayList数组,其中包含此ObservedArrayList中按正确顺序排列的所有元素。
set(ArrayList
public func set(newValue: ArrayList<T>): Unit
通过一个ArrayList数组重置当前ObservedArrayList的值。
| 参数名 | 参数类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| newValue | ArrayList |
是 | - | ArrayList数组,用来设置ObservedArrayList的值。 |
set(Array
public func set(newValue: Array<T>): Unit
| 参数名 | 参数类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| newValue | Array |
是 | - | Array数组,用来设置ObservedArrayList的值。 |
通过一个Array数组重置当前ObservedArrayList的值。
set(ObservedComplexAbstract)
public func set(newValue: ObservedComplexAbstract): Unit
通过ObservedComplexAbstract重置当前ObservedArrayList的值。
| 参数名 | 参数类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| newValue | ObservedComplexAbstract | 是 | - | ObservedComplexAbstract数据,用来设置ObservedArrayList的值。 |
public operator func [](index: Int64): T
操作符重载 - get。返回索引位置的元素的值。
| 参数名 | 参数类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| index | Int64 | 是 | - | 表示 get 接口的索引。 |
[](Int64, T)
public operator func [](index: Int64, value!: T): Unit
操作符重载 - set,通过下标运算符用指定的元素替换此列表中指定位置的元素。
| 参数名 | 参数类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| index | Int64 | 是 | - | 要设置的索引值。 |
| value | T | 是 | - | 要设置的 T 类型的值。 |
isEmpty()
public func isEmpty(): Bool
判断 ObservedArrayList 是否为空。
clone()
public func clone(): ObservedArrayList<T>
返回此ObservedArrayList实例的拷贝(浅拷贝)。
clear()
public func clear(): Unit
从此 ObservedArrayList 中删除所有元素。
append(T)
public func append(element: T): Unit
将指定的元素附加到此 ObservedArrayList 的末尾。
| 参数名 | 参数类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| element | T | 是 | - | 插入的元素。 |
appendAll(Collection
public func appendAll(elements: Collection<T>): Unit
将指定集合中的所有元素附加到此 ObservedArrayList 的末尾。
函数会按照迭代器顺序遍历入参中的集合,并且将所有元素插入到此 ObservedArrayList 的尾部。
| 参数名 | 参数类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| elements | Collection |
是 | - | 需要插入的元素的集合。 |
insert(Int64, T)
public func insert(index: Int64, element: T): Unit
在此 ObservedArrayList 中的指定位置插入指定元素。
| 参数名 | 参数类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| index | Int64 | 是 | - | 插入元素的目标索引。 |
| element | T | 是 | - | 要插入的 T 类型元素。 |
insertAll(Int64, Collection
public func insertAll(index: Int64, elements: Collection<T>): Unit
从指定位置开始,将指定集合中的所有元素插入此 ObservedArrayList。
函数会按照迭代器顺序遍历入参中的集合,并且将所有元素插入到指定位置。
| 参数名 | 参数类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| index | Int64 | 是 | - | 插入集合的目标索引。 |
| elements | Collection |
是 | - | 要插入的 T 类型元素集合。 |
prepend(T)
public func prepend(element: T): Unit
在起始位置,将指定元素插入此 ObservedArrayList。
| 参数名 | 参数类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| element | T | 是 | - | 要插入 T 类型元素。 |
prependAll(Collection
public func prependAll(elements: Collection<T>): Unit
从起始位置开始,将指定集合中的所有元素插入此 ObservedArrayList。
函数会按照迭代器顺序遍历入参中的集合,并且将所有元素插入到指定位置。
| 参数名 | 参数类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| elements | Collection |
是 | - | 要插入的 T 类型元素集合。 |
remove(Int64)
public func remove(index: Int64): T
删除此 ObservedArrayList 中指定位置的元素。返回被移除的元素。
| 参数名 | 参数类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| index | Int64 | 是 | - | 被删除元素的索引。 |
remove(Range
public func remove(range: Range<Int64>): Unit
删除此 ObservedArrayList 中 Range 范围所包含的所有元素。
| 参数名 | 参数类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| range | Range |
是 | - | 需要被删除的元素的范围。 |
removeIf((T) -> Bool)
public func removeIf(predicate: (T) -> Bool): Unit
删除此 ObservedArrayList 中满足给定 lambda 表达式或函数的所有元素。
| 参数名 | 参数类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| predicate | (T) -> Bool | 是 | - | 判断删除的条件。 |
属性
size
public prop size: Int64
此 ObservedArrayList 中的元素个数。
示例如下
@Component
class MyView {
@State var arr: ObservedArray<Int64> = ObservedArray<Int64>([1, 2])
func build() {
Column {
Text("arr[0] is ${arr[0]}")
Button("click").onClick {
arr[0] = 0
}
}
}
}
@Component
class MyView {
@State var arr: ObservedArrayList<Int64> = ObservedArrayList<Int64>([1, 2])
func build() {
Column {
Text("arr[0] is ${arr[0]}")
Button("click").onClick {
arr[0] = 0
}
Button("append").onClick {
arr.append(0)
}
}
}
}
ObservedProperty
get()
public func get(): T
读取同步属性的数据
返回值:
| 类型 | 描述 |
|---|---|
| T | 同步属性的数据。 |
示例:
AppStorage.setOrCreate<Int64>("propA", 47)
let prop1: ObservedProperty<Int64> = AppStorage.`prop`<Int64>("propA")
prop1.get() // 47
set(T)
public func set(newValue: T): Unit
设置同步属性的数据
参数:
| 参数名 | 参数类型 | 必填 | 默认值 | 描述 |
|---|---|---|---|---|
| newValue | T | 是 | - | 要设置的数据。 |
示例:
AppStorage.setOrCreate<Int64>("propA", 47)
let prop1: ObservedProperty<Int64> = AppStorage.`prop`<Int64>("propA")
prop1.set(1); // prop1.get()=1
状态更新的注意事项
不允许在spawn表达式中对状态变量进行并发修改,会导致并发安全问题。建议当需要修改状态变量时,采用concurrency包提供的launch方法,将状态更新的步骤放回主线程中运行,以保证并发安全。如下实例演示如何在spawn表达式中更新变量状态:
import ohos.base.*
import ohos.component.*
import ohos.state_manage.*
import ohos.state_macro_manage.*
import ohos.concurrency.*
import std.sync.*
import std.collection.*
import std.time.Duration
@Entry
@Component
class MyView {
@State var text: String = "begin"
func build() {
Column(30) {
Button(text).onClick { evt =>
changeText({ p: String =>
// 使用launch表达式在主线程中更新状态变量
launch {
text = p
}
})
}
}.width(100.percent)
}
private func changeText(callback: (String) -> Unit): Unit {
spawn {
while (true) {
callback("blink 0")
sleep(Duration.millisecond * 100)
callback("blink 1")
sleep(Duration.millisecond * 100)
}
}
}
}
如对您有帮助,帮忙点个“在看 、关注” 让更多的人受益~!
技术交流群可加wx“LB-9191”备注cangjie

浙公网安备 33010602011771号