Рукоять кинжала. Ошибка выполнения. Ошибка: у ViewModel нет конструктора с нулевым аргументом (котлин)

#android #kotlin #android-viewmodel #dagger-hilt

Вопрос:

Я получаю ошибку (у MainViewModel нет конструктора с нулевым аргументом). Мне кажется, что ошибка в неправильном использовании Рукояти, но я не могу найти. Есть похожие вопросы по SA, но они не подходят для моего случая. Я не могу найти, где я ошибся, и буду благодарен за любую помощь.

Ошибка:

 java.lang.RuntimeException: Cannot create an instance of class mypackage.main.MainViewModel
  /* bla bla bla */
Caused by: java.lang.InstantiationException: java.lang.Class<mypackage.main.MainViewModel> has no zero argument constructor
 at java.lang.Class.newInstance(Native Method)
 at androidx.lifecycle.ViewModelProvider$NewInstanceFactory.create(ViewModelProvider.java:219)
 ... 39 more
 

ViewModel начинается так:

 @HiltViewModel
class MainViewModel @Inject constructor(
    private val repo: MainRepository,
    private val dispatchers: DispatcherProvider
) : ViewModel() {
 
    // body
}
 

В основной деятельности:

 @AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    private val viewModel: MainViewModel by viewModels()
// etc
 

Модуль приложения:

 @Module
@InstallIn(SingletonComponent::class)
object AppModule {

    @Singleton
    @Provides
    fun provideCurrencyApi() : CurrencyApi = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .addConverterFactory(GsonConverterFactory.create())
        .build()
        .create(CurrencyApi::class.java)

    @Singleton
    @Provides
    fun provideMainRepository(api: CurrencyApi): MainRepository = DefaultMainRepository(api)

    @Singleton
    @Provides
    fun provideDispatchers(): // blablabla
    }
}
 

Основное средство:

 interface MainRepository {
    suspend fun getRates(base: String) : Resource<CurrencyResponse>
    }
 

Defaultmainрепозиция

 class DefaultMainRepository @Inject constructor(
    private val api: CurrencyApi
) : MainRepository {

    override suspend fun getRates(base: String): Resource<CurrencyResponse> {
        return try {
            val response = api.getRates(base)
            val result = response.body()
            if (response.isSuccessful amp;amp; result != null) {
                Resource.Success(result)
            } else {
                Resource.Error(response.message())
            }
        } catch (e: Exception) {
            Resource.Error(e.message ?: "An error occurred")
        }
    }
}
 

Комментарии:

1. Удалите @Inject constructor и то, и другое из вашего MainViewModel и. DefaultMainRepository Вам это не нужно, так как вы уже предоставляете их из модуля dagger

2. Спасибо за совет, но это приводит к той же ошибке

3. Пожалуйста, также обеспечьте MainViewModel использование модуля dagger при удалении @Inject constructor

4. вы не можете передать интерфейс напрямую в качестве конструктора , необходимо привязать его

Ответ №1:

Я решил эту проблему, изменив версии зависимостей рукояти кинжала на более ранние. Я думаю, что в этих версиях было несоответствие. Похоже, остальная часть кода оказалась правильной..

Комментарии:

1. Какую версию вы в итоге использовали? Я использую 2.28.3-alpha для рукояти кинжала и 1.0.0-alpha03 для andreoidx.рукоять:модель представления жизненного цикла рукояти и компилятор рукояти, и она работает так же, как и ваша…

2. Добавив к моему последнему комментарию, я обновил до версии 2.3.7 и удалил зависимости для androidx.hilt:hilt-lifecycle-viewmodel и hilt-компилятор, поскольку они больше не нужны. Большое спасибо.

3. Теперь я использую более старую: реализацию «com.google. кинжал:рукоять-android:2.28-альфа» капт «com.google. кинжал:эфес-android-компилятор:2.28-альфа» реализация «androidx.эфес:эфес-жизненный цикл-модель представления:1.0.0-alpha02» капт «androidx.эфес:эфес-компилятор:1.0.0-alpha02» Но я думаю, что, когда я использовал новейшие версии, я просто что-то неправильно с ними сделал, возможно, было какое-то несоответствие между ними.