Reputation: 6918
Now I using the viewModelFactory to init the argument for viewModel in fragment.
class MyFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val binding = FragmentMyBinding.inflate(inflater)
binding.lifecycleOwner = this
val argument = MyFragmentArgs.fromBundle(requireArgument()).myArgument
val viewModelFactory = MyViewModelFactory(myArgument, application)
binding.viewModel = ViewModelProvider(
this, viewModelFactory).get(MyViewModel::class.java)
return binding.root
}
}
class MyViewModelFactory(
private val myArgument: MyArgument,
private val application: Application) : ViewModelProvider.Factory {
@Suppress("unchecked_cast")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(MyViewModel::class.java)) {
return MyViewModel(myArgument, application) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
Compare to the hilt dependency inject way, is there a way to pass argument to viewModel directly?
Upvotes: 3
Views: 5624
Reputation: 10619
You can do it using Hilt library. You should first define your view model by @HiltViewModel
and use constructor injection(@Inject
for constructor of your view model):
@HiltViewModel
class MainViewModel @Inject constructor(val foo: Foo) : ViewModel()
My Foo class is:
class Foo @Inject constructor(val someDependency: Dependency)
If you have any other class which you need to inject to your ViewModel, you can add it to your hilt module.
Finally, you should instantiate your ViewModel in your activity/fragment:
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {
val mainViewModel: MainViewModel by viewModels()
}
Please note that we are talking only about build time dependencies. For runtime dependencies with Hilt, you still have to stick to a classic ViewModelProvider.Factory
since @AssistedInject
is not yet supported by it.
Upvotes: 2
Reputation: 11754
Yes. With Hilt, you can completely ditch the factory pattern.
To inject a param, you can use @ViewModelInject
annotation, and to inject the viewModel
in the activity you can use the by viewModels()
method from androidx.activity
package.
Here's an example.
ProductsViewModel.kt
import androidx.hilt.lifecycle.ViewModelInject
class ProductsViewModel @ViewModelInject constructor(
private val foo: Foo
private val bar: Bar
) : ViewModel()
ProductsActivity.kt
@AndroidEntryPoint
class ProductsActivity : AppCompatActivity(){
val viewModel: ProductsViewModel by viewModels()
}
To see this in action, you can checkout this repo.
Upvotes: 2