I create FrameLayout
programmatically. I give it unique id - myFrameLayoutId
- and apply View#doOnAttach
listener, and then add to the hierarchy.
Within the listener I perform an operation, which relies on findViewById(myFrameLayoutId)
. I've begun receiving very rare crash, which implies that findViewById(myFrameLayoutId)
returns null
sometimes.
Thus I wonder:
View.doOnAttach
callback guarantees that View
is findable?findViewById
?1. Does the call to View.doOnAttach callback guarantee that View is findable?
No, the doOnAttach callback does not guarantee that the View is findable via findViewById. The doOnAttach function is called when the view is attached to a window, but it does not guarantee that the view hierarchy is completely set up or that the parent has updated its child references.
2. What is the correct way to postpone some action until the point when the view can be found by the findViewById?
You can use
ViewTreeObserver.OnPreDrawListener
. This listener is called before drawing a view. By this time, the view hierarchy should be fully established, so findViewById should work as expected.
Example:
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
References:
The official Android documentation provides information on ViewTreeObserver and its various listeners, including the OnPreDrawListener.
The doOnAttach function is a Kotlin extension function provided by the Android KTX library. The documentation for this can be found in the Android KTX reference.