Как разрешить ViewModel RunTimeException - PullRequest
0 голосов
/ 29 мая 2019

Мой класс ViewModel выбрасывает RunTimeException. По сути, он не может создать экземпляр класса ViewModel. Вот трассировка стека:

2019-05-29 01:27:56.700 9698-9698/com.example.cryptpass_kt E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.cryptpass_kt, PID: 9698
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.cryptpass_kt/com.example.cryptpass_kt.MainActivity}: java.lang.RuntimeException: Cannot create an instance of class com.example.cryptpass_kt.EntryViewModel
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2853)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2928)
        at android.app.ActivityThread.-wrap11(Unknown Source:0)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1609)
        at android.os.Handler.dispatchMessage(Handler.java:105)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6703)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:769)
     Caused by: java.lang.RuntimeException: Cannot create an instance of class com.example.cryptpass_kt.EntryViewModel
        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:208)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:135)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:103)
        at com.example.cryptpass_kt.MainActivity.onCreate(MainActivity.kt:40)
        at android.app.Activity.performCreate(Activity.java:6980)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2806)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2928) 
        at android.app.ActivityThread.-wrap11(Unknown Source:0) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1609) 
        at android.os.Handler.dispatchMessage(Handler.java:105) 
        at android.os.Looper.loop(Looper.java:164) 
        at android.app.ActivityThread.main(ActivityThread.java:6703) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:769) 
     Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Constructor.newInstance0(Native Method)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:334)
        at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:200)
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:135) 
        at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:103) 
        at com.example.cryptpass_kt.MainActivity.onCreate(MainActivity.kt:40) 
        at android.app.Activity.performCreate(Activity.java:6980) 
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214) 
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2806) 
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2928) 
        at android.app.ActivityThread.-wrap11(Unknown Source:0) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1609) 
        at android.os.Handler.dispatchMessage(Handler.java:105) 
        at android.os.Looper.loop(Looper.java:164) 
        at android.app.ActivityThread.main(ActivityThread.java:6703) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:769) 
     Caused by: java.lang.RuntimeException: cannot find implementation for com.example.cryptpass_kt.EntryDatabase. EntryDatabase_Impl does not exist
        at androidx.room.Room.getGeneratedImplementation(Room.java:94)
        at androidx.room.RoomDatabase$Builder.build(RoomDatabase.java:667)
        at com.example.cryptpass_kt.EntryDatabase$Companion.getInstance(EntryDatabase.kt:17)
        at com.example.cryptpass_kt.EntryRepository.<init>(EntryRepository.kt:12)
        at com.example.cryptpass_kt.EntryViewModel.<init>(EntryViewModel.kt:8)

Ошибка указывает на 4 различных местоположения в приложении, которые все связаны с одной и той же проблемой. Например, эти строки в методе onCreate() моего MainActivity.kt находятся в трассировке стека:

override fun onCreate(savedInstanceState: Bundle?) {
    ...
    viewModel = ViewModelProviders.of(this).get(EntryViewModel::class.java)
    viewModel.allEntries.observe(this, Observer { entries -> adapter.submitList(entries) })

    ...
}

Я следовал некоторым советам в SO, например, инициализировал объект ViewModel как lateinit, а не null, но пока он не внес никаких изменений в ситуацию

EntryViewModel.kt

class EntryViewModel(application: Application) : AndroidViewModel(application) {
    private val repository: EntryRepository = EntryRepository(application)
    val allEntries: LiveData<List<Entry>>

    init {
        allEntries = repository.allEntries!!
    }

    fun insert(entry: Entry) {
        repository.insert(entry)
    }

    fun update(entry: Entry) {
        repository.update(entry)
    }

    fun delete(entry: Entry) {
        repository.update(entry)
    }

    fun deleteAll() {
        repository.deleteAllEntries()
    }
}

EntryDatabase.kt

@Database(entities = [Entry::class], version = 1)
abstract class EntryDatabase : RoomDatabase() {

    abstract fun entryDAO(): EntryDAO

    companion object{
        private var instance: EntryDatabase? = null

        @Synchronized
        fun getInstance(context: Context): EntryDatabase{
            if(instance == null){instance = Room.databaseBuilder<EntryDatabase>(context.applicationContext, EntryDatabase::class.java, "entry_database").fallbackToDestructiveMigration().build()}

            return instance as EntryDatabase
        }
    }
}

И у меня есть все необходимые зависимости gradle:

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'androidx.core:core-ktx:1.0.2'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'androidx.recyclerview:recyclerview:1.1.0-alpha05'
    implementation 'androidx.cardview:cardview:1.0.0'
    implementation 'com.android.support:design:28.1.0'

    implementation "android.arch.lifecycle:extensions:2.2.0-alpha01"
    implementation "android.arch.persistence.room:runtime:2.1.0-beta01"
    implementation "android.arch.paging:runtime:2.1.0-beta01"

    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'

    implementation 'io.sentry:sentry-android:1.7.16'
    implementation 'org.slf4j:slf4j-nop:1.7.25'
}

Ответы [ 2 ]

1 голос
/ 29 мая 2019

Попробуйте с этим

val viewModel = ViewModelProviders.of(this).get(EntryViewModel::class.java)

и в вашем приложении build.gradle

    implementation 'android.arch.lifecycle:extensions:1.1.1'
0 голосов
/ 29 мая 2019

В стековой трассе вы разместили исключения, которые были помещены одна в другую. Таким образом, последний является основным корнем проблемы:

Caused by: java.lang.RuntimeException: cannot find implementation for com.example.cryptpass_kt.EntryDatabase. EntryDatabase_Impl does not exist
at androidx.room.Room...

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

О коде вашей базы данных: есть несколько возможных причин.

1. Зависимости.

Как я видел в других ответах на подобные вопросы (я думаю, этот лучший), вы должны добавить некоторые зависимости gradle:

// Extensions = ViewModel + LiveData
implementation "android.arch.lifecycle:extensions:1.1.0"
kapt "android.arch.lifecycle:compiler:1.1.0"
// Room
implementation "android.arch.persistence.room:runtime:1.0.0"
kapt "android.arch.persistence.room:compiler:1.0.0"

Если я правильно понял, Kotlin просто нужны дополнительные зависимости (для этого используйте ключевое слово kapt вместо implementation).

2. Аннотации.

Другая возможная причина: вы не поместили аннотацию Entity в свой класс Entry (как сказано в в этом ответе ). Другая необходимая аннотация - Database, но она у вас уже есть.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...