上次吐槽鸿蒙仍是是刚刚读完官网文档。
最近测验运用鸿神的玩安卓开放 API 写一个 WanHarmony,也是遇到了一些规划上的不合理,或者是我没有 get 到规划精华的地方,记载一下。
没有大局 Style
在安卓中,遇到需求公共的样式,一般会抽取大局 Style,鸿蒙也提供了相似的能力 @Style 装修器。例如宽高都是 100% :
@Styles function matchSize() {
.width('100%')
.height('100%')
}
文档中说是支持 组件内 和 大局 重用。但实际测验,所谓的大局仅仅支持单个文件内的不同组件能够引证到,一旦跨文件就无法引证。
这个还挺不方便的,期望后续得到修复。
隐晦的 LazyForEach
LazyForEach 从提供的数据源中按需迭代数据,并在每次迭代过程中创立相应的组件。当在翻滚容器中运用了 LazyForEach,框架会根据翻滚容器可视区域按需创立组件,当组件滑出可视区域外时,框架会进行组件销毁收回以降低内存占用。
显而易见,LazyForEach 是 RecyclerView 的替代品,甚至连用法都有一些相似。
LazyForEach(
dataSource: IDataSource, // 需求进行数据迭代的数据源
itemGenerator: (item: any, index?: number) => void, // 子组件生成函数
keyGenerator?: (item: any, index?: number) => string // 键值生成函数
): void
数据源需求完成 IDataSource 接口:
interface IDataSource {
totalCount(): number; // 取得数据总数
getData(index: number): Object; // 获取索引值对应的数据
registerDataChangeListener(listener: DataChangeListener): void; // 注册数据改动的监听器
unregisterDataChangeListener(listener: DataChangeListener): void; // 刊出数据改动的监听器
}
这个 Listener 也是一堆接口方法:
interface DataChangeListener {
onDataReloaded(): void; // 从头加载数据完成后调用
onDataAdded(index: number): void; // 增加数据完成后调用
onDataMoved(from: number, to: number): void; // 数据移动开始方位与数据移动方针方位交流完成后调用
onDataDeleted(index: number): void; // 删除数据完成后调用
onDataChanged(index: number): void; // 改动数据完成后调用
onDataAdd(index: number): void; // 增加数据完成后调用
onDataMove(from: number, to: number): void; // 数据移动开始方位与数据移动方针方位交流完成后调用
onDataDelete(index: number): void; // 删除数据完成后调用
onDataChange(index: number): void; // 改动数据完成后调用
}
乍看起来,跟 RecyclerView.Adapter 差不多。等等,ArkUI 不应该是声明式 UI 吗?为什么还要用这种写法来完成列表呢。
其实 ArkUI 也有声明式的 List 组件:
List({ scroller: this.scroller }) {
ForEach(this.articleList, (item: ArticleEntity) => {
ListItem() {
ArticleView({ article: item })
.onClick(() => {
router.pushUrl({
url: 'pages/WebPage',
params: item
}, router.RouterMode.Single)
})
}
})
}
.height('100%')
.width('100%')
但是呢,默认会加载所有数据,不支持预加载,不支持 item 的收回复用。所以,屏蔽完成细节,直接让 List 支持收回复用会不会更好呢?
隐晦的 Dialog
期望的声明式 Dialog 写法:
.dialog($isShow) {
// 自定义 dialog 布局
}
鸿蒙需求通过一个奇特的 CustomDialogController 来处理。
先通过 @CustomDialog 定义自定义 Dialog,
@CustomDialog
struct CustomDialogExample {
controller: CustomDialogController = new CustomDialogController({
builder: CustomDialogExample({}),
})
build() {
Column() {
Text('自定义 Dialog')
.fontSize(20)
.margin({ top: 10, bottom: 10 })
}
}
}
然后声明一个 CustomDialogController,调用其 open() 方法来展现弹窗。
@Entry
@Component
struct CustomDialogUser {
dialogController: CustomDialogController = new CustomDialogController({
builder: CustomDialogExample(),
})
build() {
Column() {
Button('click me')
.onClick(() => {
this.dialogController.open()
})
}.width('100%').margin({ top: 5 })
}
}
官网示例中还有一个愈加晦涩难明的 一个 dialog 中弹出另一个 dialog 的场景示例。
能用,但没那么好用。
硬编码
良好的规划应该防止让程序员硬编码,以尽量减少犯错的可能性。
当我第一次看到下面这个代码,有点懵。
Grid() {
...
}
.rowsTemplate('1fr 1fr 1fr')
.columnsTemplate('1fr 2fr 1fr')
这种相比 GridLayoutManager.SpanSizeLookUp 的写法,效率确实得到了很大的提高,但可读性就降低了。
还有宽高的硬编码,
.width('100%')
.height('100%')
我一直期望能够有个相似 fillWidth/fillHeight
的装修器能够替代一下。
最终
以上吐槽基于 API 10 版别。别的期望提前能够有 API 9 以上版别的虚拟机能够运用。
今天是鸿蒙生态千帆启航仪式,目前已经参与鸿蒙原生开发的 App 数量比我幻想的还要多一些,官方也给出了 Q4 正式商用的方案。能够幻想,本年肯定是鸿蒙 App 井喷的一年。