Viewmodel factory? is it something i need?

Issue

I am programing a app in kotlin using MVVM structure and trying to instantiate my viewmodel through my factory… though im getting a trouble when i start app that 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

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 but he is using Kotlin synthetics and what i understand that has been deprecated. Here is the link anyways https://resocoder.com/2018/09/07/mvvm-on-android-crash-course-kotlin-android-architecture-components/

Solution

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 }

Answered By – sweak

Leave a Comment