kotlin.KotlinNullPointerException 从本地房间数据库访问数据时?
kotlin.KotlinNullPointerException while accessing Data from local Room Database?
我是 Kotlin 的新手,正在尝试学习如何通过改造获取数据并将这些数据存储到 Room DB 中。但是,一旦我开始执行此过程的 Activity,我就会收到 NullPointerException。
编辑:据我所知,我在 RoomViewmodel class 中的 "database" 在我想访问它时仍然是 NULL,即使我有一个覆盖 oncreate 函数,其中它已创建
这里还有一个 link 来自我正在处理的迷你项目的 GitHub 存储库:https://github.com/Engin92/Dog_Breeds/tree/RoomDatabase
这是我的完整错误列表:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.dogbreeds, PID: 14803
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.dogbreeds/com.example.Breedlist.activity.DetailedViewActivity}: kotlin.KotlinNullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3782)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3961)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:91)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:149)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:103)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2386)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:8178)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)
Caused by: kotlin.KotlinNullPointerException
at com.example.Breedlist.activity.DetailedViewActivityRepository.getBreeds(DetailedViewActivityRepository.kt:23)
at com.example.Breedlist.activity.DetailedViewActivityViewModel.getAllBreedList(DetailedViewActivityViewModel.kt:23)
at com.example.Breedlist.activity.DetailedViewActivity.onCreate(DetailedViewActivity.kt:42)
at android.app.Activity.performCreate(Activity.java:8086)
at android.app.Activity.performCreate(Activity.java:8074)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1313)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3755)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3961)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:91)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:149)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:103)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2386)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:8178)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)
DetailedView的重要部分Activity
class DetailedViewActivity : AppCompatActivity() {
lateinit var breedRecyclerView: RecyclerView
lateinit var detailedViewActivityViewModel: DetailedViewActivityViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_detailed_view)
breedRecyclerView = findViewById(R.id.breedRecyclerView)
detailedViewActivityViewModel = ViewModelProviders.of(this).get(
DetailedViewActivityViewModel::class.java)
if(isOnline(this))
{
detailedViewActivityViewModel.getBreedsFromAPIAndStore()
}
else
{
Toast.makeText(this,"No internet connection. Showing cached list!",Toast.LENGTH_LONG).show()
}
detailedViewActivityViewModel.getAllBreedList().observe(this, Observer<List<CurrentBreedResponseItem>> { breedList ->
Log.e(MainActivity::class.java.simpleName,breedList.toString())
setUpBreedRecyclerView(breedList!!)
})
} ....
class RoomViewModel,我在其中构建数据库(我认为错误在于,在尝试访问 (write/read) 之后,var 数据库仍然为 NULL)
class RoomViewModel : Application() {
companion object {
var database: BreedDatabase? = null
}
override fun onCreate() {
super.onCreate()
database = Room.databaseBuilder(applicationContext, BreedDatabase::class.java, "breed_db").fallbackToDestructiveMigration().build()
}
}
DetailedView 中的 getBreeds 函数Activity存储库:
fun getBreeds() : LiveData<List<CurrentBreedResponseItem>>
{
return RoomViewModel.database!!.currentBreedDao().getAllBreeds()
}
DetailedViewActivityViewModel
中的 getAllBreedList 函数
fun getAllBreedList(): LiveData<List<CurrentBreedResponseItem>>
{
return detailedViewActivityRepository.getBreeds()
}
你的代码有两个问题。第一个非常清楚,您正在尝试访问一个空对象,并且您得到了 NullPointerException。所以在使用 !!
运算符时要小心。
您得到它的原因是,在您的 RoomViewModel 中,您的数据库实例为空。
class RoomViewModel : Application() {
companion object {
var database: BreedDatabase? = null
}
override fun onCreate() {
super.onCreate()
database = Room.databaseBuilder(applicationContext, BreedDatabase::class.java, "breed_db")
.fallbackToDestructiveMigration().build()
}
}
您可能认为您正在 onCreate()
中初始化数据库实例,但 onCreate()
没有被调用。原因是要使应用程序 class 正常工作,您需要将其添加到 AndroidManifest.xml 文件中。
解法:
像这样将 RoomViewModel
class 添加到您的 AndroidManifest.xml 文件中。
<application
android:name=".view.RoomViewModel"
android:allowBackup="true"
如上所示,我们将其作为应用程序标签的名称属性来实现。
这将修复您的空指针异常。但是你的程序会再次崩溃,因为你正在使用 Kotlin 并且确实需要在你的应用程序级别 build.gradle 文件中添加这个东西。
kapt "android.arch.persistence.room:compiler:1.1.1"
将其添加到依赖项块内的应用级别 build.gradle 后。同步您的项目,运行 它应该可以工作。
如果您想在 Android 中了解有关房间数据库的更多信息,可以查看此 Room Database Tutorial。
希望这对您有所帮助。
我是 Kotlin 的新手,正在尝试学习如何通过改造获取数据并将这些数据存储到 Room DB 中。但是,一旦我开始执行此过程的 Activity,我就会收到 NullPointerException。
编辑:据我所知,我在 RoomViewmodel class 中的 "database" 在我想访问它时仍然是 NULL,即使我有一个覆盖 oncreate 函数,其中它已创建
这里还有一个 link 来自我正在处理的迷你项目的 GitHub 存储库:https://github.com/Engin92/Dog_Breeds/tree/RoomDatabase
这是我的完整错误列表:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.dogbreeds, PID: 14803
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.dogbreeds/com.example.Breedlist.activity.DetailedViewActivity}: kotlin.KotlinNullPointerException
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3782)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3961)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:91)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:149)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:103)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2386)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:8178)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)
Caused by: kotlin.KotlinNullPointerException
at com.example.Breedlist.activity.DetailedViewActivityRepository.getBreeds(DetailedViewActivityRepository.kt:23)
at com.example.Breedlist.activity.DetailedViewActivityViewModel.getAllBreedList(DetailedViewActivityViewModel.kt:23)
at com.example.Breedlist.activity.DetailedViewActivity.onCreate(DetailedViewActivity.kt:42)
at android.app.Activity.performCreate(Activity.java:8086)
at android.app.Activity.performCreate(Activity.java:8074)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1313)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3755)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3961)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:91)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:149)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:103)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2386)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:8178)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)
DetailedView的重要部分Activity
class DetailedViewActivity : AppCompatActivity() {
lateinit var breedRecyclerView: RecyclerView
lateinit var detailedViewActivityViewModel: DetailedViewActivityViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_detailed_view)
breedRecyclerView = findViewById(R.id.breedRecyclerView)
detailedViewActivityViewModel = ViewModelProviders.of(this).get(
DetailedViewActivityViewModel::class.java)
if(isOnline(this))
{
detailedViewActivityViewModel.getBreedsFromAPIAndStore()
}
else
{
Toast.makeText(this,"No internet connection. Showing cached list!",Toast.LENGTH_LONG).show()
}
detailedViewActivityViewModel.getAllBreedList().observe(this, Observer<List<CurrentBreedResponseItem>> { breedList ->
Log.e(MainActivity::class.java.simpleName,breedList.toString())
setUpBreedRecyclerView(breedList!!)
})
} ....
class RoomViewModel,我在其中构建数据库(我认为错误在于,在尝试访问 (write/read) 之后,var 数据库仍然为 NULL)
class RoomViewModel : Application() {
companion object {
var database: BreedDatabase? = null
}
override fun onCreate() {
super.onCreate()
database = Room.databaseBuilder(applicationContext, BreedDatabase::class.java, "breed_db").fallbackToDestructiveMigration().build()
}
}
DetailedView 中的 getBreeds 函数Activity存储库:
fun getBreeds() : LiveData<List<CurrentBreedResponseItem>>
{
return RoomViewModel.database!!.currentBreedDao().getAllBreeds()
}
DetailedViewActivityViewModel
中的 getAllBreedList 函数fun getAllBreedList(): LiveData<List<CurrentBreedResponseItem>>
{
return detailedViewActivityRepository.getBreeds()
}
你的代码有两个问题。第一个非常清楚,您正在尝试访问一个空对象,并且您得到了 NullPointerException。所以在使用 !!
运算符时要小心。
您得到它的原因是,在您的 RoomViewModel 中,您的数据库实例为空。
class RoomViewModel : Application() {
companion object {
var database: BreedDatabase? = null
}
override fun onCreate() {
super.onCreate()
database = Room.databaseBuilder(applicationContext, BreedDatabase::class.java, "breed_db")
.fallbackToDestructiveMigration().build()
}
}
您可能认为您正在 onCreate()
中初始化数据库实例,但 onCreate()
没有被调用。原因是要使应用程序 class 正常工作,您需要将其添加到 AndroidManifest.xml 文件中。
解法:
像这样将 RoomViewModel
class 添加到您的 AndroidManifest.xml 文件中。
<application
android:name=".view.RoomViewModel"
android:allowBackup="true"
如上所示,我们将其作为应用程序标签的名称属性来实现。 这将修复您的空指针异常。但是你的程序会再次崩溃,因为你正在使用 Kotlin 并且确实需要在你的应用程序级别 build.gradle 文件中添加这个东西。
kapt "android.arch.persistence.room:compiler:1.1.1"
将其添加到依赖项块内的应用级别 build.gradle 后。同步您的项目,运行 它应该可以工作。
如果您想在 Android 中了解有关房间数据库的更多信息,可以查看此 Room Database Tutorial。
希望这对您有所帮助。