I have a large project where i was getting this exception - replace() called on item that was not placed. I was able to narrow the root of the problem to having a Constraint Layout within a NavHost. I created an extremely simplified project where it is reproducible. I emphasize simplified, bc the consraintlayout is not even used properly here, constraints not applied - that's on purpose, to simplify and show that it doesnt matter in this case (in the real project, all constraints in place) Github link to the simplified project here Also, relevant code snippets below. If I call the MainContent() directly, no issues. If i call thru NavHost, i get a crash when i scroll thru the lazycolumn.
Questions
java.lang.IllegalStateException: replace() called on item that was not placed at androidx.compose.ui.node.LayoutNodeLayoutDelegate$LookaheadPassDelegate.replace(LayoutNodeLayoutDelegate.kt:1569) at androidx.compose.ui.node.LayoutNode.lookaheadReplace$ui_release(LayoutNode.kt:923) at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureAndRelayoutIfNeeded
and specifically this is the code in Layoutnode.kt from Compose:
internal fun lookaheadReplace() {
if (intrinsicsUsageByParent == UsageByParent.NotUsed) {
// This LayoutNode may have asked children for intrinsics. If so, we should
// clear the intrinsics usage for everything that was requested previously.
clearSubtreePlacementIntrinsicsUsage()
}
**lookaheadPassDelegate!!.replace()**
}
Activity:
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
// MainContent() -- this works
val navController = rememberNavController()
// with NavHost, it crashes.
NavHost(
navController,
startDestination = NavRoutes.MainRoute.name
) {
mainGraph()
}
}
}
}
Main Graph:
fun NavGraphBuilder.mainGraph(
) {
navigation(startDestination = MainNavOption.Main.name, route = NavRoutes.MainRoute.name) {
composable(MainNavOption.Main.name){
MainContent()
}
}
}
Main Content:
@Composable
fun MainContent() {
WhyConstraintTheme {
val listState = rememberLazyListState()
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
var listItems = mutableListOf<ElementHolder>()
for (i in 1.rangeTo(149)) {
listItems.add(ElementHolder(i.toString()))
}
BoxWithConstraints(Modifier.fillMaxSize()) {
LazyColumn(
state = listState,
contentPadding = PaddingValues(1.dp),
verticalArrangement = Arrangement.Center
) {
items(listItems) { item: ElementHolder ->
ElementListItem(
element = item.itemDescription,
)
}
}
}
}
}
}
Element H
@Composable fun ElementListItem( element: String, ) {
ConstraintLayout() {
val (
divider, year, description, image,
overflow
) = createRefs()
Text(
text = "element: {$element}",
modifier = Modifier.constrainAs(year) {
linkTo(
start = parent.start,
end = parent.end,
)
}
)
}
}
Versions used (btw, tried with many different versions, going back to a number of previous versions)
val material_version = "1.5.4" implementation ("androidx.compose.material:material:$material_version")
implementation ("androidx.compose.material:material-icons-extended:$material_version") implementation("androidx.core:core-ktx:1.12.0") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2") implementation("androidx.activity:activity-compose:1.8.1") implementation(platform("androidx.compose:compose-bom:2023.10.01")) implementation("androidx.compose.ui:ui") implementation("androidx.compose.ui:ui-graphics") implementation("androidx.compose.ui:ui-tooling-preview") implementation("androidx.compose.material3:material3") implementation ("androidx.constraintlayout:constraintlayout-compose:1.0.1")
implementation ("androidx.navigation:navigation-compose:2.7.5")
EDIT: Another trigger for crash is AnimatedContent. If you wrap the LazyColumn with a constraint layout inside an AnimatedContent (instead of NavHost), same crash happens. So probably the ultimate root cause has something to do with animations inside both NavHost and AnimatedContent - a Composable inside NavHost has AnimatedContentScope.
A fix for the crash seems to be upgrading the ConstraintLayout
from 1.0.1
to 1.1.0-alpha13
.