Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I need ViewModelFactory in android?

I am trying to pass a constructor parameter in the ViewModel class. But I don't understand the best approach to do this. Please take a look at the code and comment and let me know the easiest and appropriate way.

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

    // Question 1: How can I pass constructor parameter if I use this delegate feature?
    // private lateint var viewModel: MainViewModel by viewModels()

    private lateinit var viewModel: MainViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val repository = Repository()

        // Passing constructor directly works.
        viewModel = MainViewModel(repository)

        // Question 2: Why do I need this factory class / method as it works without these two lines.

//        val viewModelFactory = MainViewModelFactory(repository)
//        viewModel = ViewModelProvider(this, viewModelFactory).get(MainViewModel::class.java)


        viewModel.getPost()
        viewModel.mResponse.observe(this, Observer { response ->
            if (response.isSuccessful) {
                Log.d("Response: ", response.body()?.userId.toString())
                Log.d("Response: ", response.body()?.id.toString())
                binding.textView.text = response.body()?.title.toString()
                Log.d("Response: ", response.body()?.body.toString())
            } else {
                Log.d("Response: ", response.errorBody().toString())
                binding.textView.text = response.code().toString()
            }
        })

    }
}
like image 605
Code Lover Avatar asked Oct 18 '25 16:10

Code Lover


1 Answers

// Question 1: How can I pass constructor parameter if I use this delegate feature?
// private lateint var viewModel: MainViewModel by viewModels()

You would pass your ViewModelFactory as a parameter to viewModels(). Or, depending on the nature of the parameter, use a dependency inversion framework (Dagger/Hilt, Koin, etc.). In your case, you seem to be passing some sort of repository, in which case a dependency inversion framework is a popular solution.

   // Question 2: Why do I need this factory class / method as it works without these two lines.

Because it does not actually work. In particular, that MainViewModel instance does not survive a configuration change (e.g., screen rotation). If you want to use the Jetpack ViewModel system correctly, the ViewModel system has to instantitate your MainViewModel.

like image 146
CommonsWare Avatar answered Oct 21 '25 06:10

CommonsWare