我以编程方式创建
FrameLayout
。我给它唯一的 id - myFrameLayoutId
- 并应用 View#doOnAttach
侦听器,然后添加到层次结构。
在侦听器中,我执行一个操作,该操作依赖于
findViewById(myFrameLayoutId)
。我开始收到非常罕见的崩溃,这意味着 findViewById(myFrameLayoutId)
有时会返回 null
。
因此我想知道:
View.doOnAttach
回调是否能保证 View
是可找到的?findViewById
找到视图的那一刻,正确的方法是什么?1。调用View.doOnAttach回调是否保证View可找到?
不,doOnAttach回调不能保证可以通过findViewById找到视图。当视图附加到 window 时,会调用 doOnAttach 函数,但它不能保证视图层次结构已完全设置或父级已更新其子级引用。
2。推迟某些操作直到可以通过 findViewById 找到视图的时间点的正确方法是什么?
您可以使用
。在绘制视图之前调用此侦听器。此时,视图层次结构应该已完全建立,因此 findViewById 应该按预期工作。ViewTreeObserver.OnPreDrawListener
示例:
val frameLayout = FrameLayout(context)
frameLayout.id = myFrameLayoutId
frameLayout.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {
override fun onPreDraw(): Boolean {
frameLayout.viewTreeObserver.removeOnPreDrawListener(this) // Important to remove after being called
// By this time, the view hierarchy should be ready
val foundView = findViewById<View>(myFrameLayoutId)
// Your logic here
return true
}
})
// Add the frameLayout to your view hierarchy
参考资料:
Android 官方文档提供了有关 ViewTreeObserver 及其各种侦听器(包括 OnPreDrawListener)的信息。
doOnAttach 函数是 Android KTX 库提供的 Kotlin 扩展函数。有关此内容的文档可以在Android KTX 参考中找到。