Viewmodel factory? is it something i need?

521 Views Asked by At

I am programing an app in kotlin using MVVM structur. i tried to instantiate my viewmodel through my factory. Though im getting an error when i start the app. It says this `

java.lang.RuntimeException: Cannot create an instance of class com.example.paperseller.ui.menu.ViewModels.AuthViewModel

I have no clue at all why im getting this trouble. My code looks like this

I have already tried to skip the factory implementation. I would not use this way of implementing mvvm in kotlin nowadays. I would take a look at renewed tutorials 2021.

LoginRegister_fragment:

package com.example.paperseller.ui.menu
import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.EditText
import android.widget.Toast
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.example.paperseller.Data.User
import com.example.paperseller.R
import com.example.paperseller.databinding.LoginRegisterFragmentBinding
import com.example.paperseller.ui.menu.ViewModels.AuthViewModel



class LoginRegister_fragment : Fragment(R.layout.login_register_fragment) {
    private var _binding : LoginRegisterFragmentBinding? = null
    private val binding get() = _binding!!

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View?
    {
        _binding = LoginRegisterFragmentBinding.inflate(inflater, container, false)
        return binding.root

    }
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        initializeUI()

    }

    private fun initializeUI()
    {
        val factory = InjectorUtils.providePaperSellerViewModelFactory()
        val viewModel : AuthViewModel by viewmodels()

        viewModel.message.observe(this)
        {
            message ->
            Toast.makeText(requireActivity(), message, Toast.LENGTH_LONG).show()
        }

        binding.registerButton.setOnClickListener()
        {
            val user = User(binding.emailText.text.toString(), binding.passwordText.text.toString());

            viewModel.register(user)

        }
    }
    override fun onDestroy() {
        super.onDestroy()
        _binding = null
    }


}

ViewModelFactory:

package com.example.paperseller.ui.menu.ViewModelFactory

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.example.paperseller.Data.PaperSellerRepository
import com.example.paperseller.ui.menu.ViewModels.AuthViewModel

class PaperSellerViewModelFactory(private val paperSellerRepository: PaperSellerRepository) : ViewModelProvider.NewInstanceFactory()
{
    @Suppress("UNCHECKED_CAST")
    override fun <T:ViewModel?> create(modelClass: Class<T>):T{
        return AuthViewModel(paperSellerRepository) as T
    }
}

I tried to follow this tutorial: https://resocoder.com/2018/09/07/mvvm-on-android-crash-course-kotlin-

This tutorial is 4 years old. Tip to people seeing this question later. Check tutorials on youtube that is up to date this helped me alot.

1

There are 1 best solutions below

3
On BEST ANSWER

Your ViewModel takes in a repository and since then You have to use the ViewModelFactory. You can either use ViewModelProvider:

val factory = InjectorUtils.providePaperSellerViewModelFactory()
val viewModel = ViewModelProvider(
    this,
    factory)
    .get(AuthViewModel::class.java)

or, as @IR42 has pointed out, You can use viewModels delegate:

val viewModel: AuthViewModel by viewModels { factory }