Created
May 12, 2022 17:49
-
-
Save richardleggett/938000cdfabe62e833ab97c6460268ef to your computer and use it in GitHub Desktop.
AssistedInject HiltViewModels for Compose Navigation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Screen VM | |
class ScreenOneViewModel @AssistedInject constructor( | |
// deviceManager is scoped to a flow's sub-NavGraph | |
@Assisted private val deviceManager: SomeBLEDeviceManager, | |
@Assisted private val someIdArg: Int, | |
logger: Logger, | |
otherThing: SomeOtherDependency, | |
) : CoroutineViewModel<ViewState, UiAction> { ... } | |
// Screen Composable - Compose Destination | |
@Destination | |
@Composable | |
fun ScreenOne( | |
navigator: MyFlowNavigator, | |
deviceManager: SomeBLEDeviceManager, | |
someIdArg: Int, // NavArg | |
) { | |
val factory = hiltViewModel<FactoriesViewModel>().screenOneVmFactory | |
val viewModel: ScreenOneViewModel = viewModelByFactory { factory.create(deviceManager, someIdArg) } | |
BackHandler { navigator.popBackStack() } | |
val state by viewModel.viewStateStream().collectAsState() | |
... | |
} | |
// utility to grab a viewModel() for an Assisted.Factory | |
@Composable | |
inline fun <reified VM : ViewModel, T> viewModelByFactory(crossinline creator: () -> T): VM { | |
@Suppress("UNCHECKED_CAST") | |
val vmFactory = object : ViewModelProvider.Factory { | |
override fun <T : ViewModel> create(modelClass: Class<T>): T { | |
return creator.invoke() as T | |
} | |
} | |
return viewModel(factory = vmFactory) | |
} | |
// HiltViewModel as the glue between Dagger and Compose NavGraph | |
@HiltViewModel | |
class FactoriesViewModel @Inject constructor( | |
val screen1VmFactory: ScreenOneViewModel.Factory, | |
val screen2VmFactory: ScreenTwoViewModel.Factory, | |
val screen3VmFactory: ScreenThreeViewModel.Factory, | |
) : ViewModel() | |
// NavGraph-scoped dependencies | |
@Module | |
@InstallIn(ViewModelComponent::class) | |
interface DeviceFlowModule { | |
@Binds | |
fun bindDeviceManager(deviceManagerImpl: SomeBLEDeviceManagerImpl): SomeBLEDeviceManager | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@AssistedInject
et al are expect/actual in KMM, typealias to Dagger.