Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change the way the Compose interop works to avoid Android 12 bug #1370

Merged
merged 2 commits into from
Jan 25, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 41 additions & 1 deletion epoxy-compose/src/main/java/com/airbnb/epoxy/ComposeInterop.kt
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,28 @@ fun ModelCollector.composableInterop(
vararg keys: Any,
composeFunction: @Composable () -> Unit
) {
add(composeEpoxyModel(id, *keys, composeFunction = composeFunction))
// Note this is done to avoid ART bug in Android 12 (background https://issuetracker.google.com/issues/197818595 and
// https://github.com/airbnb/epoxy/issues/1199).
// The main objective is to have the creation of the ComposeEpoxyModel the setting of the id and the adding to the
// controller in the same method.
// Note that even this manual inlining might be spoiled by R8 outlining which, if enabled might outline the creation
// of the ComposeEpoxyModel and setting of the id to a separate method.
val composeEpoxyModel = ComposeEpoxyModel(*keys, composeFunction = composeFunction)
composeEpoxyModel.id(id)
add(composeEpoxyModel)
}

/**
* [composeEpoxyModel] can be used directly in cases where more control over the epoxy model
* is needed. Eg. When the epoxy model needs to be modified before it's added.
*/
@Deprecated(
message = "Use composeEpoxyModel with modelAction lambda instead to avoid crash on Android 12",
replaceWith = ReplaceWith(
expression = "composeEpoxyModel(id, *keys, modelAction = modelAction, composeFunction = composeFunction)",
imports = ["com.airbnb.epoxy.composeEpoxyModel"]
)
)
fun composeEpoxyModel(
id: String,
vararg keys: Any,
Expand All @@ -86,6 +101,31 @@ fun composeEpoxyModel(
}
}

/**
* [composeEpoxyModel] can be used directly in cases where more control over the epoxy model
* is needed. Eg. When the epoxy model needs to be modified before it's added.
*
* Note: This does not return the model and instead takes a modelAction lambda that can be used to
* add the model to the controller, or modify it before adding.
*
* This is done to avoid ART bug in Android 12 (background https://issuetracker.google.com/issues/197818595 and
* https://github.com/airbnb/epoxy/issues/1199).
* The main objective is to have the creation of the ComposeEpoxyModel the setting of the id and
* the adding to the controller in the same method.
* Note that even with this construct this might be spoiled by R8 outlining which, if enabled might
* outline the creation of the ComposeEpoxyModel and setting of the id to a separate method.
*/
inline fun composeEpoxyModel(
id: String,
vararg keys: Any,
noinline composeFunction: @Composable () -> Unit,
modelAction: (ComposeEpoxyModel) -> Unit
) {
val composeEpoxyModel = ComposeEpoxyModel(*keys, composeFunction = composeFunction)
composeEpoxyModel.id(id)
modelAction.invoke(composeEpoxyModel)
}

@Composable
inline fun <reified T : EpoxyModel<*>> EpoxyInterop(
modifier: Modifier = Modifier,
Expand Down
Loading