在有人说这之前已经被回答之前,我已经阅读并尝试了下面列出的帖子中的推荐解决方案:
我尝试在build.gradle文件中添加依赖项,尝试使用ViewModel类的不同实现,但没有任何改变。
我得到的主要错误是
Process: com.example.infinityquiz, PID: 12107
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.infinityquiz/com.example.infinityquiz.MainActivity}: java.lang.RuntimeException: Cannot create an instance of class com.example.infinityquiz.viewmodel.QuestionViewModel
在下面,我列出了我当前的相关代码。如果您认为缺少重要的代码,请告诉我。
Build.gradle
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
apply plugin: 'androidx.navigation.safeargs.kotlin'
android {
compileSdkVersion 29
buildToolsVersion "30.0.0"
defaultConfig {
applicationId "com.example.infinityquiz"
minSdkVersion 23
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.1'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
testImplementation 'junit:junit:4.13'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
// Navigation Component
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.0'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.0'
// Room components
implementation "androidx.room:room-runtime:2.2.5"
kapt "androidx.room:room-compiler:2.2.5"
implementation "androidx.room:room-ktx:2.2.5"
androidTestImplementation "androidx.room:room-testing:2.2.5"
implementation "androidx.paging:paging-runtime:2.1.2"
// Lifecycle components
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "androidx.lifecycle:lifecycle-common-java8:2.2.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
// Kotlin components
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72"
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7"
api "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.5"
// Extensions = ViewModel + LiveData
implementation "android.arch.lifecycle:extensions:1.1.1"
kapt "android.arch.lifecycle:compiler:1.1.1"
// Room
implementation "android.arch.persistence.room:runtime:1.1.1"
kapt "android.arch.persistence.room:compiler:1.1.1"
implementation 'androidx.fragment:fragment:1.2.5'
}
ViewModel
package com.example.infinityquiz.viewmodel
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import com.example.infinityquiz.data.QuestionDatabase
import com.example.infinityquiz.model.Question
import com.example.infinityquiz.repository.QuestionRepository
class QuestionViewModel(application: Application): AndroidViewModel(application) {
val question: Question
private val repository:QuestionRepository
init {
val questionDao = QuestionDatabase.getDatabase(
application
).questionDao()
repository = QuestionRepository(questionDao)
question = repository.question
}
}
存储库
package com.example.infinityquiz.repository
import com.example.infinityquiz.data.QuestionDao
import com.example.infinityquiz.model.Question
class QuestionRepository(private val questionDao: QuestionDao) {
val question: Question = questionDao.readRandomQuestion()
}
Dao
package com.example.infinityquiz.data
import androidx.room.Dao
import androidx.room.Query
import com.example.infinityquiz.model.Question
/*
private const val TABLE_NAME = "multiple_choice_questions"
private const val QUERY = "SELECT * FROM $TABLE_NAME ORDER BY RANDOM() LIMIT 1"
*/
@Dao
interface QuestionDao {
@Query("SELECT * FROM multiple_choice_questions ORDER BY RANDOM() LIMIT 1")
fun readRandomQuestion(): Question
}
问题
package com.example.infinityquiz.model
import android.os.Parcelable
import androidx.room.Entity
import androidx.room.PrimaryKey
import kotlinx.android.parcel.Parcelize
@Parcelize
@Entity(tableName = "multiple_choice_questions")//, foreignKeys=[], indices=[])
data class Question (
@PrimaryKey(autoGenerate = true)
val id: Int,
val Question: String,
val Category: String,
val Subcategory: String,
val AnswerOne: String,
val AnswerTwo: String,
val AnswerThree: String,
val AnswerFour: String,
val CorrectAnswer: Int,
val wasQuestionSeen: Int,
val Wikipedia: String
): Parcelable
主要活动(部分)
package com.example.infinityquiz
import android.graphics.Color
import android.graphics.Typeface
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.lifecycle.ViewModelProvider
import com.example.infinityquiz.model.Question
import com.example.infinityquiz.viewmodel.QuestionViewModel
import kotlinx.android.synthetic.main.activity_quiz_questions.*
class MainActivity : AppCompatActivity(), View.OnClickListener{
private lateinit var mQuestionViewModel: QuestionViewModel
private var question: Question? = null
private var mSelectedOptionPosition: Int = 0
/**
* This function is auto created by Android when the Activity Class is created.
*/
override fun onCreate(savedInstanceState: Bundle?) {
//This call the parent constructor
super.onCreate(savedInstanceState)
// This is used to align the xml view to this class
setContentView(R.layout.activity_main)
mQuestionViewModel = ViewModelProvider(this, ViewModelProvider.AndroidViewModelFactory.getInstance(this.application)).get(QuestionViewModel::class.java)
// mQuestionViewModel = ViewModelProvider(this).get(QuestionViewModel::class.java)
setQuestion()
tv_option_one.setOnClickListener(this)
tv_option_two.setOnClickListener(this)
tv_option_three.setOnClickListener(this)
tv_option_four.setOnClickListener(this)
btn_submit.setOnClickListener(this)
}
.
.
.
}
数据库
package com.example.infinityquiz.data
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import com.example.infinityquiz.model.Question
@Database(entities = [Question::class], version = 1)
abstract class QuestionDatabase: RoomDatabase() {
abstract fun questionDao(): QuestionDao
companion object {
@Volatile
private var INSTANCE: QuestionDatabase? = null
private const val PATH = "database/data_eng.db"
private const val NAME = "multiple_choice_questions"
private fun buildDatabase(context: Context) =
Room.databaseBuilder(context.applicationContext, QuestionDatabase::class.java, NAME).createFromAsset(PATH).build()
fun getDatabase(context: Context): QuestionDatabase{
val tempInstance = INSTANCE
if(tempInstance != null){
return tempInstance
}
synchronized(this){
val instance = buildDatabase(context)
INSTANCE = instance
return instance
}
}
}
}
错误消息
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.infinityquiz, PID: 12107
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.infinityquiz/com.example.infinityquiz.MainActivity}: java.lang.RuntimeException: Cannot create an instance of class com.example.infinityquiz.viewmodel.QuestionViewModel
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.lang.RuntimeException: Cannot create an instance of class com.example.infinityquiz.viewmodel.QuestionViewModel
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:275)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
at com.example.infinityquiz.MainActivity.onCreate(MainActivity.kt:32)
at android.app.Activity.performCreate(Activity.java:7802)
at android.app.Activity.performCreate(Activity.java:7791)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:267)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:187)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:150)
at com.example.infinityquiz.MainActivity.onCreate(MainActivity.kt:32)
at android.app.Activity.performCreate(Activity.java:7802)
at android.app.Activity.performCreate(Activity.java:7791)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.lang.IllegalStateException: Pre-packaged database has an invalid schema: multiple_choice_questions(com.example.infinityquiz.model.Question).
Expected:
TableInfo{name='multiple_choice_questions', columns={Category=Column{name='Category', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, Subcategory=Column{name='Subcategory', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, wasQuestionSeen=Column{name='wasQuestionSeen', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, AnswerThree=Column{name='AnswerThree', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, Wikipedia=Column{name='Wikipedia', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, Question=Column{name='Question', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, id=Column{name='id', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='null'}, AnswerOne=Column{name='AnswerOne', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, CorrectAnswer=Column{name='CorrectAnswer', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, AnswerTwo=Column{name='AnswerTwo', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, AnswerFour=Column{name='AnswerFour', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}
Found:
TableInfo{name='multiple_choice_questions', columns={}, foreignKeys=[], indices=[]}
at androidx.room.RoomOpenHelper.checkIdentity(RoomOpenHelper.java:163)
E/AndroidRuntime: at androidx.room.RoomOpenHelper.onOpen(RoomOpenHelper.java:135)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.onOpen(FrameworkSQLiteOpenHelper.java:142)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:428)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:317)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getWritableSupportDatabase(FrameworkSQLiteOpenHelper.java:92)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper.getWritableDatabase(FrameworkSQLiteOpenHelper.java:53)
at androidx.room.SQLiteCopyOpenHelper.getWritableDatabase(SQLiteCopyOpenHelper.java:90)
at androidx.room.RoomDatabase.inTransaction(RoomDatabase.java:476)
at androidx.room.RoomDatabase.assertNotSuspendingTransaction(RoomDatabase.java:281)
at com.example.infinityquiz.data.QuestionDao_Impl.readRandomQuestion(QuestionDao_Impl.java:25)
at com.example.infinityquiz.repository.QuestionRepository.<init>(QuestionRepository.kt:7)
at com.example.infinityquiz.viewmodel.QuestionViewModel.<init>(QuestionViewModel.kt:17)
... 21 more
Disconnected from the target VM, address: 'localhost:8608', transport: 'socket'
我无法立即解决此问题。谢谢您的提前帮助。