Search code examples
androiddagger-2android-viewmodeldagger-hilt

Cannot create an instance of class ViewModel - android


I have ViewModel like bellow:

class LoginViewModel(
    private val networkAvailable: NetworkAvailable,
    private val app: Application,
    private val getLoginUseCase: GetLoginUseCase
) : AndroidViewModel(app) {
  .....
}

And here is LoginViewModelFactory:

class LoginViewModelFactory(
    private val networkAvailable: NetworkAvailable,
    private val app: Application,
    private val getLoginUseCase: GetLoginUseCase
) : ViewModelProvider.Factory {
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        return LoginViewModel(
            networkAvailable,
            app,
            getLoginUseCase
        ) as T
    }
}

I edited like bellow but not work:

@Module
@InstallIn(SingletonComponent::class)
class LoginModule {

    @Singleton
    @Provides
    fun provideLoginViewModelFactory(
        networkAvailable: NetworkAvailable,
        application: Application,
        getLoginUseCase: GetLoginUseCase
    ): LoginViewModelFactory {
        return LoginViewModelFactory(
            networkAvailable,
            application,
            getLoginUseCase,
        )
    }
}

And:

@Singleton
class NetworkAvailable @Inject constructor(@ApplicationContext private val context: Context) {

    fun isNetworkConnected(): Boolean {
        var result = false
        val connectivityManager =
            context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S_V2) {
            val networkCapabilities = connectivityManager.activeNetwork ?: return false
            val activeNetwork =
                connectivityManager.getNetworkCapabilities(networkCapabilities) ?: return false
            result = when {
                activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
                activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
                activeNetwork.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
                else -> false
            }
        } else {
            connectivityManager.run {
                connectivityManager.activeNetworkInfo?.run {
                    result = when (type) {
                        ConnectivityManager.TYPE_WIFI -> true
                        ConnectivityManager.TYPE_MOBILE -> true
                        ConnectivityManager.TYPE_ETHERNET -> true
                        else -> false
                    }

                }
            }
        }

        return result
    }
}

And here:

class GetLoginUseCase(private val loginRepository: LoginRepository) {

    suspend fun execute(userName: String, pass: String): Resource<LoginMainEntity> {
        return loginRepository.getLogin(userName, pass)
    }
}

And:

@Module
@InstallIn(SingletonComponent::class)
class UseCaseModule {

    @Singleton
    @Provides
    fun provideGetLoginUseCase(loginRepository: LoginRepository): GetLoginUseCase {
        return GetLoginUseCase(loginRepository)
    }

}

And:

@AndroidEntryPoint
class LoginActivity : AppCompatActivity() {
    @Inject
    lateinit var factory: LoginViewModelFactory
    private lateinit var loginViewModel: LoginViewModel

   override fun onCreate(savedInstanceState: Bundle?) {
     ......
       loginViewModel = ViewModelProvider(this, factory)[LoginViewModel::class.java]
        loginViewModel.loginValues("AAAQQQ", "123456")
   }

I can't call LoginViewModel


Solution

  • When using a custom constructor,
    we define a ViewModelProvider.Factory which you did but did not use it.

    Instantiate your factory like this:

    class MainActivity: AppCompatActivity() {
    
      private val viewModel: MyViewModel by viewModels {
          LoginViewModelFactory(networkAvailable, application, loginUseCase)
      }
    
      // other things
    }