```private fun ensureCompositionCreated() { if...
# compose
m
Copy code
private fun ensureCompositionCreated() {
    if (composition == null) {
        try {
            creatingComposition = true
            composition = setContent(resolveParentCompositionContext()) {
                Content()
            }
        } finally {
            creatingComposition = false
        }
    }
}
What’s going on in this method from the
AbstractComposeView
class?
Copy code
private var creatingComposition = false
private fun checkAddView() {
    if (!creatingComposition) {
        throw UnsupportedOperationException(
            "Cannot add views to " +
                "${javaClass.simpleName}; only Compose content is supported"
        )
    }
}
The class has these members also, and a bunch of methods (e.g.
addView
) that guard their bodies with a call to
checkAddView
at the start:
Copy code
override fun addView(child: View?) {
    checkAddView()
    super.addView(child)
}
Does this mean that…
Copy code
composition = setContent(resolveParentCompositionContext()) {
                Content()
            }
…there might be parallel threads that also have concurrent access to the receiver (
AbstractComposeView
) and they’re only allowed to call methods such as
addView
while the assignment above is running? What happens if: 1. Thread A calls
ensureCompositionCreated
on an
AbstractComposeView
2. While the assignment is running, thread B also calls the same method on the same instance 3. One thread finishes first and sets
creatingComposition = false
while the other is still running 4. Thread C calls
addView
which in turn first calls
checkAddView
on the same instance of
AbstractComposeView
Wouldn’t that result in the
creatingComposition
property incorrectly being set to
false
even though there’s a creation process running (namely in the slower thread)? Why should the methods guarded by
checkAddView
only be called a) concurrently b) while a composition is being created in parallel anyway?
🧵 3
z
AbstractComposeView
only ever has a single child: an
AndroidComposeView
. That child actually wires up most of the connections between the view system and compose.
Views should never be accessed by any threads other than the one that created them, in general. There are lots of checks to enforce this.
m
How can the
addView
method and its friends ever be useful if the view is not meant to be accessed concurrently? They all have the
checkAddView
check at the start, and it only succeeds if the view is currently in the middle of the assignment
z
Not to be pedantic, but concurrent ≠ multithreaded
I believe the AndroidComposeView is added when the composition is created.
m
Right, I remember seeing that. So the flag is turned on for the RHS of the assignment. Thanks for the clarification