DEV Community

Abdalla Elnaggar
Abdalla Elnaggar

Posted on • Edited on

ViewModel runtime dependencies or not?

We all know ViewModel is build to hold ui state and survive configuration change, so by this given it should retrieve the data needed to create ui state as soon as possible, most of the time that mean when you initialize it, what if you need to pass an id to that ViewModel like postId or articleId, when you use hilt the dependencies of the Viewmodel must be known at compile time if you want Hilt to inject them without any effort, what happen if you want to pass runtime dependencies,
the solution:
first: create @AssistedFactory Annotated Interface

@AssistedFactory
interface UserViewModelAssistedFactory {
    fun create(name: String): UserViewModel
}
Enter fullscreen mode Exit fullscreen mode

second: create factory class or object

class Factory(  
        private val assistedFactory: UserViewModelAssistedFactory,  
        private val name: String,  
    ) : ViewModelProvider.Factory {  
        override fun <T : ViewModel?> create(modelClass: Class<T>): T {  
            return assistedFactory.create(name) as T  
        }
    }
Enter fullscreen mode Exit fullscreen mode

third: inject the factory in fragment and use it to create the viewModle

@Inject 
lateinit var assistedFactory: UserViewModelAssistedFactory  
private val userViewModel: UserViewModel by viewModels {  
    UserViewModel.Factory(assistedFactory, navArgs.name)  
}
Enter fullscreen mode Exit fullscreen mode

this is so much right I felt the same.
it turns out that if your dependices is coming from Navigation argument you can use the provided by defualt SavedStateHandle to get that navArgs, it comes with this version,

implementation 'androidx.navigation:navigation-ui-ktx:2.4.1'
Enter fullscreen mode Exit fullscreen mode

you can access navigation arguments through the saved state handle

@HiltViewModel
class RecentChatViewModel @Inject constructor(
    private val getRecentChatUseCase: GetRecentChatUseCase,
    savedStateHandle: SavedStateHandle
) : ViewModel() {
    private val accountId: Int = RecentChatFragmentArgs.
fromSavedStateHandle(savedStateHandle).accountId
Enter fullscreen mode Exit fullscreen mode

be careful you will need to update your compile sdk to 31 if
you are not.
it is simple right why I had to search so much me and my friend Elfiky to reach out this simple solution.
I copied some code from this article because I am lazy

Top comments (0)