什么是声明式UI?
传统的命令式ui需要先获取到数据,然后显示调用ui元素的刷新ui方法把数据塞进去才能完成ui刷新。
声明式UI相比命令式UI,就要简洁很多,把ui和数据绑定后,数据变化后ui自动就刷新了,少了显示调用ui刷新的方法。
一、结合mvvm来看
在MVVM里面,view和viewModel之间是这种自动关联的,利用声明式ui能很轻松的实现这种效果。
二、在鸿蒙中的声明式UI
在鸿蒙里面,view对应component组件;viewModel对应自定义的Manager;model对应数据类或者数据管理仓库。
其中view和viewModel使用状态变量和声明式ui可以实现这种绑定效果,下面举个例子,为了简单就简化model层,突出view和viewModel层
View层:
@Component
struct testPage {
@StorageProp("storage_test") testData: string = ''
build() {
Text(this.testData)
.onClick(() => {
viewModel.getData()
})
}
}
ViewModel层:
class MyViewModel {
async getData() {
//模拟耗时操作
setTimeout(() => {
const timeStamp = systemDateTime.getTime().toString()
AppStorage.setOrCreate<string>("storage_test", timeStamp)
},1000)
}
}
export const viewModel = new MyViewModel()
在view层点击事件触发获取数据,在viewModel获取数据后保存在appStorage里面,view层对应的text和appStorage相关的数据就会刷新ui。这里appStorage可以认为是一种特殊的状态变量。
三、在安卓中的声明式UI
对应的在安卓的compose,也是声明式ui
其中view层对应@compose组件,viewModel对应安卓jetpack内置的viewModel组件,model对应数据类
下面是一个和鸿蒙类似的简单例子:
view层
@Composable
fun Greeting(modifier: Modifier = Modifier, viewModel: MyViewModel = viewModel()) {
ClickableText(
text = AnnotatedString(viewModel.strData.value),
onClick = {
viewModel.getStateData()
},
modifier = modifier
)
}
viewModel层:
class MyViewModel : ViewModel() {
val strData = mutableStateOf("111111")
fun getStateData() {
viewModelScope.launch {
strData.value = "loading...."
withContext(Dispatchers.IO) {
//模拟耗时操作
delay(1000)
}
strData.value = System.currentTimeMillis().toString()
}
}
}
安卓的声明式ui用到的对应是compose以及mutableState,也是在compose组件内部点击事件触发获取数据,viewModel里面获取数据保存在mutableState里面,view层对应的text和mutableState相关的数据就会自动刷新。
四、鸿蒙和安卓对比看
两边对比如下表格
| view | viewModel | 状态变量 | |
|---|---|---|---|
| 鸿蒙 | @Component | 工程师自定义管理类 | appStorage |
| 安卓 | @Compose | 安卓jetpack内置组件 | mutableState |
可以看到几乎是一样的,整个声明式UI步骤大差不差。
其中由于鸿蒙是第一版,历史代码包袱少,使用起来还是比安卓的compose简洁一些。
通过对比安卓以前命令式ui方式,使用componse少了xml,少了dataBading,使用componse比之前xml简洁很多。