How to Get Activity From Jetpack Compose

Safely get current Activity in Composable

Ji Sungbin
Better Programming

--

Photo by Samuel Schwendener on Unsplash

When working with Compose, there are often times when you need to get an Activity. For example, I need an Activity to call finish() in a situation where the screen needs to close when a button is pressed. However, there is currently no built-in method for directly getting an Activity in which composable is placed. In this article, I’m going to introduce 3 ways to get an Activity in Compose.

LocalContext.current as Activity

The easiest and simplest way is LocalContext.current as Activity. Just casting Context to Activity. In a way, this can be a very dangerous method. But I think it’s safe. To understand why this is a safe way to do this, we must first look at how LocalContext is provided.

All composable start from ComponentActivity.setContent, where all composition data(including LocalContext) are initialized.

If you look at setContent, ComposeView is initialized with the Activity that called setContent through ComposeView(this). After that, the composition initialization process proceeds through ComposeView(this).setContent(content).

In that process, the ProvideAndroidCompositionLocals function is called. You can see that most CompositionLocals are provided here, and LocalContext is also provided. The owner received as an argument becomes ComposeView initialized with Activity earlier, and the Context is obtained from this ComposeView and provided as LocalContext.

Through this process, we can confirm that LocalContext is passing the Activity we called setContent into the Context, so LocalContext.current as Activity is safe.

LocalActivity.current

However, casting the Context to Activity can still be awkward. In that case, can create a LocalActivity and provide the Activity directly to use.

Performance Optimization Tip: Activity instances do not change often or at all, so creating a CompositionLocal with staticCompositionLocalOf eliminates the unnecessary process of tracking values change, which reduces overhead and optimizes performance.

setContent {
CompositionLocalProvider(LocalActivity provides this) {
composable()
}
}

Only need to provide provides once before using composable, it is propagated, so composables with the same root can easily get Activity through LocalActivity.current.

Who knows how data is stored inside Compose, may be concerned about memory leaks by just putting Activity into an array. (All composition data, including CompositionLocal data, is managed in an Array<Any?> array)

All composable have a process of erasing all data used by composable assigned to the Activity if the Activity disappears. So there is no memory leak.

Context.findActivity()

Finally, the method used by Google and the safest method.

This is the code being used in accompanist/permissions and it is searching for Activity while iterating in Context. It throws when the Activity is not found until the end, so it is a good method for those who want the strongest safety.

The End!

In this way, I have introduced three methods of get Activity from Composable that I know of. If you have a better method or a method you are using, please share it in the comments!

Thanks for reading.

[View in Korean]

Reviewed by Gibson Ruitiari. thanks!

--

--

Experience Engineers for us. I love development that creates references.