Search code examples
androidkotlinandroid-intentandroid-activityviewmodel

Cannot create an instance of class ViewModel & ViewModel has no zero argument constructor when starting Activity


I'm getting this error while I'm starting an Activity and the app crashed. The stack trace returned the 2 errors I mentioned in the title. These are my codes :

This is the Activity I'm starting :

class FavoriteUserListActivity : AppCompatActivity() {

    private lateinit var binding: ActivityFavoriteUserListBinding
    private lateinit var viewModel: FavoriteUserListViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityFavoriteUserListBinding.inflate(layoutInflater)
        setContentView(binding.root)

        viewModel = ViewModelProvider.AndroidViewModelFactory(application).create(FavoriteUserListViewModel::class.java)

        viewModel.getAllFavorites().observe(this){user : List<FavoriteUserEntity>? ->
            val items = arrayListOf<ItemsItem>()
            if (user != null) {
                user.map{
                    val item = it.avatarUrl?.let { it1 -> ItemsItem(
                        gistsUrl = "",
                        reposUrl = "",
                        followingUrl = "",
                        login = it.username,
                        type = "",
                        subscriptionsUrl = "",
                        siteAdmin = false,
                        id = 0,
                        gravatarId = "",
                        organizationsUrl = "",
                        starredUrl = "",
                        followersUrl = "",
                        url = "",
                        receivedEventsUrl = "",
                        avatarUrl = it.avatarUrl!!,
                        eventsUrl = "",
                        htmlUrl = "",
                        nodeId = "",
                        score = "",
//                        login = it.username,
//                        avatarUrl = it1
                    ) }
                    if (item != null) {
                        items.add(item)
                    }
                }
            }
            binding.rvFavuser.adapter = UsersAdapter(items)
        }
    }
}

This is the ViewModel Factory :

class ViewModelFactory private constructor(private val mApplication: Application): ViewModelProvider.NewInstanceFactory(){
    companion object {
        @Volatile
        private var INSTANCE: ViewModelFactory? = null

        @JvmStatic
        fun getInstance(application: Application): ViewModelFactory{
            if (INSTANCE == null){
                synchronized(ViewModelFactory::class.java){
                    INSTANCE = ViewModelFactory(application)
                }
            }
            return INSTANCE as ViewModelFactory
        }
    }

    @Suppress("UNCHECKED_CAST")
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(DetailViewModel::class.java)){
            return DetailViewModel(mApplication) as T
        } else if (modelClass.isAssignableFrom(FavoriteUserListViewModel::class.java)){
            return FavoriteUserListViewModel(mApplication) as T
        }
        throw IllegalArgumentException("Unknown Viewmodel class: ${modelClass.name}")
    }
}

And this is the ViewModel for the Activity :

class FavoriteUserListViewModel(application: Application): ViewModel() {

    private val _listFavorites = MutableLiveData<FavoriteUserEntity>()
    val listFavorites : LiveData<FavoriteUserEntity> = _listFavorites

    private val mFavoriteUserRepository : FavoriteUserRepository = FavoriteUserRepository(application)

    fun getAllFavorites(): LiveData<List<FavoriteUserEntity>> {
        return mFavoriteUserRepository.getAllFavorites()
    }
}

I tried to initialize the ViewModel using the code below but it still returns error I mentioned :

viewModel = ViewModelProvider(this).get(FavoriteUserListViewModel::class.java)

Solution

  • Your code:

    viewModel = ViewModelProvider(this).get(FavoriteUserListViewModel::class.java)
    

    is almost correct, you should provide additional parameter to it,

    viewModel = ViewModelProvider(this, ViewModelFactory.getInstance(application)).get(FavoriteUserListViewModel::class.java)