踩坑记-databinding
问题
每次进入详情页,标题栏都会闪一下,特别是图标部分,很明显,可以看下面的gif
如果不明显,可以看下面两张对比图片
异常态
正常态
可以看到,在打开详情页的动画过程中,会闪一下异常的UI
问题分析
首先看下现有的代码
<TextView
style="@style/detail_tag_style"
android:layout_marginRight="6dp"
android:text="@string/platform_offers"
android:visibility="@{(item.isCashBack == true)?View.VISIBLE:View.GONE}" />
<ImageView
android:id="@+id/ivAllowInvoice"
android:background="@drawable/icon_invoice"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginRight="6dp"
android:visibility="@{(item.allowInvoice == true)?View.VISIBLE:View.GONE}" />
可以看到,布局是使用databinding来实现的,用item的值来判断可见性,自行验证了下,item的值没有问题,设置item是在onbindviewholder设置的,我们看下代码
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
val detailItem = detail.spuDetailResult
if (holder is ImageItemHolder) {
//忽略
} else if (holder is DetailTopHolder) {
holder.topBinding.item = detailItem //绑定数据的地方
//其他代码忽略
}
}
topBinding的对象是ItemDetailTopItemBinding,设置item的方法,是AS自动生成的,叫做ItemDetailTopItemBindingImpl,具体实现在这个类里面
public void setItem(@Nullable com.ygp.mro.data.GoodsDetail Item) {
this.mItem = Item;
synchronized(this) {
mDirtyFlags |= 0x1L;
}
notifyPropertyChanged(BR.item);
super.requestRebind(); //这里触发刷新
}
继续往下看
protected void requestRebind() {
//其他代码忽略
if (USE_CHOREOGRAPHER) {
mChoreographer.postFrameCallback(mFrameCallback);
} else {
mUIThreadHandler.post(mRebindRunnable);
}
}
最终实现的是mChoreographer.postFrameCallback方法,可以知道,其实是异步实现的,所以问题的是
databinding设置data是异步生效(下一次绘制),不是直接生效
问题解决
问题的解决,有两个方案
方案1:这里不用databinding,直接在onbindViewHolder代码里面,手动设置
val visilble = if (detailItem.allowInvoice) {
View.VISIBLE
} else {
View.GONE
}
holder.topBinding.ivAllowInvoice.visibility = visilble
这样就可以避免闪烁的问题了,不过同时也没有用到databidning特性了,违背了原本的设计思路
方案2:设置default属性
可以在xml里面,设置view默认为不可见
<ImageView
android:id="@+id/ivAllowInvoice"
android:background="@drawable/icon_invoice"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginRight="6dp"
android:visibility="@{(item.allowInvoice == true)?View.VISIBLE:View.GONE,default=gone}" />
最后的这个default=gone就会设置默认不可见(感谢伟华提供方案),所以也就不会闪一下了,这个default属性在官方的文档里面没有提到,还是在网上搜索到的
内部原理
为什么加了default=gone就不会闪了,抱着这个疑问,分别对比了有设置default=gone跟没有设置,自动生成的ItemDetailTopItemBinding类,有没有差别,最终发现,没有任何差别
接着怀疑,问题应该是处在最终的apk上面,于是把生成的apk的xml打开,发现如下情况
<ImageView
android:id="@ref/0x7f0a0171"
android:tag="binding_11"
android:background="@ref/0x7f08009d"
android:visibility="2"
android:layout_width="dimension(4097)"
android:layout_height="dimension(4097)"
android:layout_marginRight="dimension(1537)" />
自动给view加了visibility="2"的属性,2就是代表View.GONE,原来是在apk打包的时候,给view自动加了不可见的属性
总结
databinding设置data,是异步生效,如果碰到闪烁情况,可以加default属性 其实还有个疑问,虽然是异步生效,但其实是下一帧绘制的时候生效,理论上也是不应该出现闪烁的,这个闪烁,我发现是部分机型上才会出现,也不是所有机型必现的,这个涉及不同rom底层的实现,暂时也还没弄清楚...
相关文章
- 在 Go 里用 CGO?这 7 个问题你要关注!
- 9款优秀的去中心化通讯软件 Matrix 的客户端
- 求职数据分析,项目经验该怎么写
- 在OKR中,我看到了数据驱动业务的未来
- 火山引擎云原生大数据在金融行业的实践
- OpenHarmony富设备移植指南(二)—从postmarketOS获取移植资源
- 《数据成熟度指数》报告:64%的企业领袖认为大多数员工“不懂数据”
- OpenHarmony 小型系统兼容性测试指南
- 肯睿中国(Cloudera):2023年企业数字战略三大趋势预测
- 适用于 Linux 的十大命令行游戏
- GNOME 截图工具的新旧截图方式
- System76 即将推出的 COSMIC 桌面正在酝酿大变化
- 2GB 内存 8GB 存储即可流畅运行,Windows 11 极致精简版系统 Tiny11 发布
- 迎接 ecode:一个即将推出的具有全新图形用户界面框架的现代、轻量级代码编辑器
- loongarch架构介绍(三)—地址翻译
- Go 语言怎么解决编译器错误“err is shadowed during return”?
- 敏捷:可能被开发人员遗忘的部分
- Denodo预测2023年数据管理和分析的未来
- 利用数据推动可持续发展
- 在 Vue3 中实现 React 原生 Hooks(useState、useEffect),深入理解 React Hooks 的