https://kotlinlang.org logo
Title
j

Jitendra

06/20/2022, 3:41 AM
I need to get context in view model , I am trying to get using localcontext but it is keep giving error @composable invocation can only happen from the context of composable function, what is the best way to get context/activity instance in viewsmodel
f

Francesc

06/20/2022, 4:47 AM
Context is better avoided in viewmodels. If you still want to go that route, inject the application context using Hilt or whichever DI you're using. However, I discourage that approach.
👍 1
a

Advitiay Anand

06/20/2022, 6:05 AM
Since viewmodel has its own lifecycle, it's possible for the context (that it is holding) to go stale (no longer in memory), therefore you should avoid holding such references in the viewmodel. A simpler approach would be to create a function in the viewmodel, and pass it as a callback in your composables. Something like this:
class MyViewModel : ViewModel() {
    fun useContextToDoSomething(context: Context) {
        // Do something
    }
class MainActivity : ComponentActivity() {
    val viewModel: MyViewModel by viewModels()
setContent {
        MyComposable(doWithContext = viewModel.useContextToDoSomething)
    }
}
@Composable
fun MyComposable(doWithContext: (Context) -> Unit) {
    val context = LocalContext.current
Button(onClick = { doWithContext(context) }) {
        Text("Click Me!")
    }
}
This way, the context is always fresh, but the functionality is still kept in the viewmodel, away from the UI
👍 1
k

kotlinforandroid

06/20/2022, 1:37 PM
To further elaborate: A
ViewModel
can live longer than the
View
that uses it. That's why the reference can go stale. The
View
gets GC'd and thus its
Context
as well. A
ViewModel
in Compose is often bound to the NavGraph and thus outlives its View counterpart.
:nice: 2