Skip to content

Instantly share code, notes, and snippets.

@kamilwawrzyczek
Created June 11, 2024 17:23
Show Gist options
  • Save kamilwawrzyczek/95ba7ec995568d1b3d6ab3a9eb5fd6e2 to your computer and use it in GitHub Desktop.
Save kamilwawrzyczek/95ba7ec995568d1b3d6ab3a9eb5fd6e2 to your computer and use it in GitHub Desktop.
ViewModel injection in compose using Dagger Android
package com.example.article
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.Modifier
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewmodel.compose.viewModel
import dagger.android.AndroidInjection
import javax.inject.Inject
import javax.inject.Provider
class MyViewModel @Inject constructor() : ViewModel() {
val message = "Hello from MyViewModel!"
}
class MyInner1ViewModel @Inject constructor() : ViewModel() {
val message = "Hello from MyInner1ViewModel!"
}
class MyInner2ViewModel @Inject constructor() : ViewModel() {
val message = "Hello from MyInner2ViewModel!"
}
class DaggerViewModelFactory<T : ViewModel> @Inject constructor(
private val viewModelProvider: Provider<T>
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return viewModelProvider.get() as T
}
}
class FactoryProvider @Inject constructor(
val myVMFactory: DaggerViewModelFactory<MyViewModel>,
val myInner1VMFactory: DaggerViewModelFactory<MyInner1ViewModel>,
val myInner2VMFactory: DaggerViewModelFactory<MyInner2ViewModel>,
)
val LocalFactoryProvider = staticCompositionLocalOf<FactoryProvider> {
throw IllegalStateException("No factory provided")
}
class MyActivity : ComponentActivity() {
@Inject
lateinit var factoryProvider: FactoryProvider
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContent {
CompositionLocalProvider(LocalFactoryProvider provides factoryProvider) {
AwesomeScreen()
}
}
}
}
@Composable
fun AwesomeScreen(
viewModel: MyViewModel = viewModel(factory = LocalFactoryProvider.current.myVMFactory)
) {
Column(modifier = Modifier.fillMaxSize()) {
Text(text = viewModel.message)
MyInnerScreen1()
MyInnerScreen2()
}
}
@Composable
fun MyInnerScreen1(
viewModel: MyInner1ViewModel = viewModel(factory = LocalFactoryProvider.current.myInner1VMFactory)
) {
Text(text = viewModel.message)
}
@Composable
fun MyInnerScreen2(
viewModel: MyInner2ViewModel = viewModel(factory = LocalFactoryProvider.current.myInner2VMFactory)
) {
Text(text = viewModel.message)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment