'How to pass arguments from Activity to ViewModel using Hilt (without a ViewModel Factory)
In my activity, I have multiple variables being initiated from Intent Extras. As of now I am using ViewModelFactory to pass these variables as arguments to my viewModel.
How do I eliminate the need for ViewModelFacotory with hilt
Here are two variables in my Activity class
class CommentsActivity : AppCompatActivity() {
private lateinit var viewModel: CommentsViewModel
override fun onCreate(savedInstanceState: Bundle?) {
val contentId = intent.getStringExtra(CONTENT_ID_FIELD) //nullable strings
val highlightedCommentId = intent.getStringExtra(HIGHLIGHTED_COMMENT_ID_RF) //nullable strings
val commentsViewModelFactory = CommentsViewModelFactory(
contentId,
highlightedCommentId
)
viewModel = ViewModelProvider(this, commentsViewModelFactory[CommentsViewModel::class.java]
}
}
Here is my viewModel
class CommentsViewMode(
contentId : String?,
highlightedCo;mmentId : String?,
) : ViewModel() {
//logic code here
}
My app is already set up to use hilt but in this case How can I pass these 2 variables and eliminate the viewModelFactory entirely
Solution 1:[1]
The trick is to initialize those variables only once, while the activity can be created multiple times. In my apps, I use a flag.
View model:
class CommentsViewModel : ViewModel() {
private var initialized = false
private var contentId : String? = null
private var highlightedCommentId : String? = null
fun initialize(contentId : String?, highlightedCommentId : String?) {
if (!initialized) {
initialized = true
this.contentId = contentId
this.highlightedCommentId = highlightedCommentId
}
}
//logic code here
}
Also, you should know that there is an open issue in dagger project exactly for this capability: https://github.com/google/dagger/issues/2287
You're welcome to follow the progress.
Solution 2:[2]
If you want to use hilt effectively u can follow this steps Use @HiltViewModel in your view model
@HiltViewModel
class MyViewModel @inject constructor(private val yrParameter): ViewModel {}
Also you no longer need any ViewModelFactory! All is done for you! In your activity or fragment, you can now just use KTX viewModels() directly.
private val viewModel: MyViewModel by viewModels()
Or if you want to use base classes for fragment and activity you can use this code to pass viewModel class
abstract class BaseFragment<V: ViewModel, T: ViewDataBinding>(@LayoutRes val layout: Int, viewModelClass: Class<V>) : Fragment() {
private val mViewModel by lazy {
ViewModelProvider(this).get(viewModelClass)
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Mojtaba Shirkhani |