Varsha Myadam
Varsha Myadam

Reputation: 11

java.lang.Class has no zero argument constructor and Cannot create an instance of ViewModel

When I'm visiting the application and once accessing this fragment(MenstrualFragment), the application crashes and this is displayed in the Logcat -

2022-06-23 15:44:59.110 11278-11278/com.miniproject.monthlies E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.miniproject.monthlies, PID: 11278
    java.lang.RuntimeException: Cannot create an instance of class com.miniproject.monthlies.ui.fragments.menstruation.menstrual.MenstrualViewModel
        at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.kt:188)
        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:238)
        at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:112)
        at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:146)
        at dagger.hilt.android.internal.lifecycle.HiltViewModelFactory.create(HiltViewModelFactory.java:111)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:171)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:139)
        at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:44)
        at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:31)
        at com.miniproject.monthlies.ui.fragments.MenstrualFragment.getMViewModel(MenstrualFragment.kt:52)
        at com.miniproject.monthlies.ui.fragments.MenstrualFragment.observeViewModel(MenstrualFragment.kt:127)
        at com.miniproject.monthlies.ui.fragments.MenstrualFragment.onCreateView(MenstrualFragment.kt:72)
        at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2963)
        at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:518)
        at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282)
        at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2189)
        at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2106)
        at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:2002)
        at androidx.fragment.app.FragmentManager$5.run(FragmentManager.java:524)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:255)
        at android.app.ActivityThread.main(ActivityThread.java:8212)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:632)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1049)
     Caused by: java.lang.InstantiationException: java.lang.Class<com.miniproject.monthlies.ui.fragments.menstruation.menstrual.MenstrualViewModel> has no zero argument constructor
        at java.lang.Class.newInstance(Native Method)
        at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.kt:186)
        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.kt:238) 
        at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:112) 
        at androidx.lifecycle.SavedStateViewModelFactory.create(SavedStateViewModelFactory.java:146) 
        at dagger.hilt.android.internal.lifecycle.HiltViewModelFactory.create(HiltViewModelFactory.java:111) 
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:171) 
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.kt:139) 
        at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:44) 
        at androidx.lifecycle.ViewModelLazy.getValue(ViewModelLazy.kt:31) 
        at com.miniproject.monthlies.ui.fragments.MenstrualFragment.getMViewModel(MenstrualFragment.kt:52) 
        at com.miniproject.monthlies.ui.fragments.MenstrualFragment.observeViewModel(MenstrualFragment.kt:127) 
        at com.miniproject.monthlies.ui.fragments.MenstrualFragment.onCreateView(MenstrualFragment.kt:72) 
        at androidx.fragment.app.Fragment.performCreateView(Fragment.java:2963) 
        at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:518) 
        at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:282) 
        at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2189) 
        at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2106) 
        at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:2002) 
        at androidx.fragment.app.FragmentManager$5.run(FragmentManager.java:524) 
        at android.os.Handler.handleCallback(Handler.java:938) 
        at android.os.Handler.dispatchMessage(Handler.java:99) 
        at android.os.Looper.loop(Looper.java:255) 
        at android.app.ActivityThread.main(ActivityThread.java:8212) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:632) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1049)

MenstrualViewModel-

package com.miniproject.monthlies.ui.fragments.menstruation.menstrual

import android.content.Context
import androidx.lifecycle.MutableLiveData
import com.miniproject.monthlies.feature.mapper.MenstrualPeriodResumeMapper
import com.google.firebase.firestore.ktx.toObject
import com.miniproject.monthlies.data.firebase.FirebaseUtil
import com.miniproject.monthlies.data.model.menstrual.MenstrualPeriodMonthly
import com.miniproject.monthlies.data.model.menstrual.MenstrualPeriodResume
import com.miniproject.monthlies.data.remote.RemoteRepository
import com.miniproject.monthlies.feature.model.menstrual.MenstrualPeriodMonthlyIntent
import com.miniproject.monthlies.feature.model.menstrual.MenstrualPeriodResumeIntent
import com.miniproject.monthlies.ui.activities.base.BaseFirebaseListener
import com.miniproject.monthlies.ui.activities.base.BaseViewModel
import com.miniproject.monthlies.util.Const
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.*
import javax.inject.Inject

//@HiltViewModel
class MenstrualViewModel @Inject constructor(
    val firebaseUtil: FirebaseUtil,
    private val repository: RemoteRepository,
) : BaseViewModel() {
//private val sharePreferenceUtil: SharePreferenceUtil,
    //@ApplicationContext private val application: Context
//class MenstrualViewModel(private val repository: Repository): ViewModel() {
    private val menstrualPeriodResumeMapper = MenstrualPeriodResumeMapper.getInstance()

    var activeYear = ""

    var activeYearData: MenstrualPeriodMonthlyIntent? = null

    var maxCycleLong = 0
    var minCycleLong = 0
    var periodLong = 0
    var activeMonth = 0

    val progressGetMenstrualRecord = MutableLiveData<Boolean>()
    val successGetMenstrualRecord = MutableLiveData<MenstrualPeriodMonthlyIntent>()
    val errorGetMenstrualRecord = MutableLiveData<String>()
    fun getMenstrualPeriod(year: String){
        CoroutineScope(Dispatchers.IO).launch {
            try {
                progressGetMenstrualRecord.postValue(true)
                val user = firebaseUtil.firebaseAuth.currentUser
                activeYear = year
                periodLong = 0
                activeMonth = 0
                firebaseUtil.fireStoreDb
                    .collection(Const.COLLECTION_MENSTRUAL_PERIOD)
                    .document(user?.uid?:"")
                    .collection(activeYear)
                    .get()
                    .addOnSuccessListener {result ->
                        val menstrualPeriodMonthly = MenstrualPeriodMonthlyIntent()
                        if (!result.isEmpty){
                            for (querySnapshot in result){

                                val data = querySnapshot?.toObject<MenstrualPeriodResumeIntent>()

                                if (data != null){
                                    if (maxCycleLong == 0 && minCycleLong == 0){
                                        maxCycleLong = data.longCycle
                                        minCycleLong = data.longCycle
                                    }
                                    if (data.longCycle > maxCycleLong){
                                        maxCycleLong = data.longCycle
                                    }
                                    if (data.longCycle < minCycleLong){
                                        minCycleLong = data.longCycle
                                    }
                                    periodLong += data.longPeriod
                                    activeMonth++
                                }

                                when (querySnapshot.id){
                                    Const.KEY_JAN -> { menstrualPeriodMonthly.jan = data }
                                    Const.KEY_FEB -> { menstrualPeriodMonthly.feb = data }
                                    Const.KEY_MAR -> { menstrualPeriodMonthly.mar = data }
                                    Const.KEY_APR -> { menstrualPeriodMonthly.apr = data }
                                    Const.KEY_MAY -> { menstrualPeriodMonthly.may = data }
                                    Const.KEY_JUN -> { menstrualPeriodMonthly.jun = data }
                                    Const.KEY_JUL -> { menstrualPeriodMonthly.jul = data }
                                    Const.KEY_AUG -> { menstrualPeriodMonthly.aug = data }
                                    Const.KEY_SEP -> { menstrualPeriodMonthly.sep = data }
                                    Const.KEY_OCT -> { menstrualPeriodMonthly.oct = data }
                                    Const.KEY_NOV -> { menstrualPeriodMonthly.nov = data }
                                    Const.KEY_DEC -> { menstrualPeriodMonthly.dec = data }
                                }
                            }
                            periodLong /= activeMonth
                        }
                        progressGetMenstrualRecord.postValue(false)
                        successGetMenstrualRecord.postValue(menstrualPeriodMonthly)
                    }
                    .addOnFailureListener {exception ->
                        progressGetMenstrualRecord.postValue(false)
                        errorGetMenstrualRecord.postValue(exception.message)
                    }
            }catch (e: Exception){
                progressGetMenstrualRecord.postValue(false)
                errorGetMenstrualRecord.postValue(e.message)
            }
        }
    }

    val progressAddMenstrualRecord = MutableLiveData<Boolean>()
    val successAddMenstrualRecord = MutableLiveData<MenstrualPeriodResumeIntent>()
    val errorAddMenstrualRecord = MutableLiveData<String>()

    fun addMenstrualPeriod(menstrualPeriodResume: MenstrualPeriodResumeIntent, date: Date){
        val month = SimpleDateFormat("MMMM", Locale.US).format(date)
        addMenstrualResumeDataMonth(month, menstrualPeriodResume)
        CoroutineScope(Dispatchers.IO).launch {
            repository.addMenstrualPeriod(menstrualPeriodResumeMapper.mapFromIntent(menstrualPeriodResume)!!, object:
                BaseFirebaseListener<MenstrualPeriodResume> {
                override fun onLoading(isLoading: Boolean) {
                    progressAddMenstrualRecord.postValue(isLoading)
                }

                override fun onSuccess(data: MenstrualPeriodResume) {
                    successAddMenstrualRecord.postValue(menstrualPeriodResumeMapper.mapToIntent(data))
                }

                override fun onFailed(errorMessage: String) {
                    errorAddMenstrualRecord.postValue(errorMessage)
                }
            })
        }
    }

    fun getMenstrualResumeDataCurrentMonth(month: String): MenstrualPeriodResumeIntent? {
        return when (month){
            Const.KEY_JAN -> activeYearData?.jan
            Const.KEY_FEB -> activeYearData?.feb
            Const.KEY_MAR -> activeYearData?.mar
            Const.KEY_APR -> activeYearData?.apr
            Const.KEY_MAY -> activeYearData?.may
            Const.KEY_JUN -> activeYearData?.jun
            Const.KEY_JUL -> activeYearData?.jul
            Const.KEY_AUG -> activeYearData?.aug
            Const.KEY_SEP -> activeYearData?.sep
            Const.KEY_OCT -> activeYearData?.oct
            Const.KEY_NOV -> activeYearData?.nov
            Const.KEY_DEC -> activeYearData?.dec
            else -> null
        }
    }

    private fun addMenstrualResumeDataMonth(month: String, data: MenstrualPeriodResumeIntent) {
        when (month){
            Const.KEY_JAN -> activeYearData?.jan = data
            Const.KEY_FEB -> activeYearData?.feb = data
            Const.KEY_MAR -> activeYearData?.mar = data
            Const.KEY_APR -> activeYearData?.apr = data
            Const.KEY_MAY -> activeYearData?.may = data
            Const.KEY_JUN -> activeYearData?.jun = data
            Const.KEY_JUL -> activeYearData?.jul = data
            Const.KEY_AUG -> activeYearData?.aug = data
            Const.KEY_SEP -> activeYearData?.sep = data
            Const.KEY_OCT -> activeYearData?.oct = data
            Const.KEY_NOV -> activeYearData?.nov = data
            Const.KEY_DEC -> activeYearData?.dec = data
        }
    }
}

2 things are present in logcat i.e "cannot create an instance of ViewModel" and "ViewModel has no zero argument constructor". In this scenario, what should be done?

I recently came into the field of Android development so I'm not having much idea on what to do next.

 

Upvotes: 1

Views: 1178

Answers (2)

Naum Djordjevic
Naum Djordjevic

Reputation: 11

I was having the same error. I my case I was missing @AndroidEntryPoint annotation in fragment that created the viewModel and you need to annotate your viewModel as @HiltViewModel.

Upvotes: 0

Ivo
Ivo

Reputation: 23244

It's because you commented out @HiltViewModel.

Change

//@HiltViewModel

to

@HiltViewModel

Upvotes: 4

Related Questions