背景:
最近在使用ets编写一个app的时候,有一个需求会使用到字母索引器,我首先想到的是官方是否有该组件,如果有则直接拿过来使用,没有则自己自定义个组件。
然后翻阅了官方api文档,发现有Alphabetindexer组件可以使用,于是运行官方demo,各种编译和运行报错,然后先解决编译报错,然后解决运行报错,最后结果就是运行无效果出现。最后无奈放弃该组件,然后想着自定义一个组件来实现,在自定义组件的时候又发现目前只能支持自定义属性,而没法自定义事件,这样我自定义出来的组件又不够强大,依然不满意。然后我又回头好好研究下为何官方这个组件为何运行不了,而官方又确实有运行成功的效果图。后来我想到会不会是内部使用的IDE和sdk跟我手上的不同,就像HarmonyOS的sdk7还没有出来的时候,是先推出的OpenHarmony的sdk7支持ets的,于是我新建了一个OpenHarmony的项目来跑这个案例,结果能成功运行起来。这时终于看到希望了,那为何HarmonyOS上就跑不起来呢?预览器和模拟器运行都不行。
AlphabetIndexer组件demo代码和运行效果
@Entry
@Component
struct AlphabetIndexerComponent {
private value: string[] = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
build() {
AlphabetIndexer({ ArrayValue: this.value, selected: 0 })
.selectedColor(0xffffff) // 选中颜色
.popupColor(0xFFFAF0) // 弹出框颜色
.selectedBackgroundColor(0xCCCCCC) // 选中背景颜色
.popupBackground(0xD2B48C) // 弹出框背景颜色
.usingPopup(true) // 是否显示弹出框
.selectedFont({ size: 16, weight: FontWeight.Bolder }) // 选中的样式
.popupFont({ size: 30, weight: FontWeight.Bolder }) // 弹出框的演示
.itemSize(28) // 每一项的大小正方形
.alignStyle(IndexerAlign.Left) // 左对齐
.onSelected((index: number) => {
console.info(this.value[index] + '被选中了') // 选中的事件
})
.margin({ left: 50 })
}
}
Bug分析
这里主要的思路就是拿不正常的HarmonyOS工程和正常的OpenHarmony工程做比对。
编写好上述demo代码之后,在HarmonyOS中编译就会报错,IDE会直接在代码中飘红,截图如下:
遇到这个问题,大家首先想到的肯定是查看函数的定义,然后修改自己的代码去让编译通过。我起初也是这么做的。 下面我们看下AlphabetIndexer对应的源码,截图如下
这时候会发现就是一个字符A的大小写不匹配的小问题,然后我自然将demo中的代码的参数ArrayValue改成arrayValue,此时编译器就不会报错了。然后使用预览器运行的话直接会crash,如下图
由于预览器没有具体报错的日志,下面使用模拟器运行,看到日志如下图
这个日志依然帮助不大。 之前一直在怀疑是写的demo代码的问题,后面创建了OpenHarmony工程执行相同代码ok之后对比下OpenHarmony的sdk中的AlphabetIndexer组件的代码如下图:
这时我发现这里sdk中的ArrayValue参数是大写字母A。此时可以确认问题就是来源于此了。 那么如何解决该问题呢?
问题解决,修改HarmonyOS Sdk中的代码
修改SDK目录下的component目录下的alphabet_indexer.d.ts文件
将该文件中的arrayValue修改为ArrayValue 修改完该文件之后,只能使IDE不飘红,但是依然无法通过编译。 下面继续寻找原因,追寻下ets是如何参与编译的。于是找到了build-toolsets-loader这个关键文件夹。
修改SDK目录下的build-toolsets-loaderdeclarations下的alphabet_indexer.d.ts代码
将该文件中的arrayValue修改为ArrayValue
经过上面两步修改之后,就可以正常在HarmomyOS上运行起来该案例了。
总结
看似一个很小的bug,实际解决过程真的非常艰辛,卡了我两天时间。如果不是我偶然想到使用OpenHarmony Sdk去试一下,可能依然没定位原因。然后定位原因之后,如何去修改sdk呢?我之前写过一篇如何通过OpenHarmony源码来编译sdk的文章,但是不用这么复杂,即使我编译了也不能直接拿来给发行版的HarmonyOS进行使用。于是想想ts这类脚本语言能不能直接通过修改本地的sdk文件解决下,最终找到了上面的解决方法进行解决。当然此问题治标不治本,该问题我已经反馈给了华为,并且提供了解决方案,后面还是通过官方更新SDK来彻底解决。
|