【问题标题】:kotlin.KotlinNullPointerException while accessing Data from local Room Database?从本地房间数据库访问数据时出现 kotlin.KotlinNullPointerException?
【发布时间】:2020-09-10 16:27:33
【问题描述】:

我是 Kotlin 的新手,正在尝试学习如何通过改造获取数据并将这些数据存储到 Room DB 中。但是,一旦我启动发生此过程的 Activity,我就会得到 NullPointerException。

编辑:据我现在所知,当我想访问 RoomViewmodel 类中的“数据库”时,它仍然为 NULL,即使我有一个覆盖 oncreate 函数,它是在哪里创建的

这里也是我正在处理的小项目中指向 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) 

DetailedViewActivity的重要部分

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!!)
        })
    } ....

RoomViewModel 类,我在其中构建数据库(我认为错误所在,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()
    }
}

DetailedViewActivityRepository 中的getBreeds 函数:

fun getBreeds() : LiveData<List<CurrentBreedResponseItem>>
{
    return RoomViewModel.database!!.currentBreedDao().getAllBreeds()
}

DetailedViewActivityViewModel中的getAllBreedList函数

fun getAllBreedList(): LiveData<List<CurrentBreedResponseItem>>
{
    return detailedViewActivityRepository.getBreeds()
}

【问题讨论】:

  • 您好,我克隆了您的存储库并尝试运行它。它工作正常,我没有看到任何崩溃。你能准确解释一下它何时以及如何崩溃吗?
  • 是的,当然!当我在手机上启动该应用程序时,我立即进入第一个活动,在那里我看到了一个狗名列表。一旦我单击其中一个名称,程序就会崩溃。通常,应用程序必须通过 API 将数据保存到我的数据库中,并在第二个活动中显示。 PS:你下载的是 RoomDataBase-branch 还是 Master? RoomDataBase 分支中的存储库是一个,它不起作用
  • 您在DetailedViewActivityRepository.kt:23 处访问的内容为空。请不要链接到整个存储库。审阅者更难浏览整​​个项目,这根本不需要提供答案。
  • @sonnet 据我现在所知,当我想访问它时,我在 RoomViewmodel 类中的“数据库”仍然为 NULL,即使我有一个覆盖 oncreate 函数,它是在哪里创建的?!

标签: database kotlin nullpointerexception retrofit android-room


【解决方案1】:

您的代码中有两个问题。第一个非常清楚,您正在尝试访问一个空对象并且您得到 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() 没有被调用。原因是要使应用程序类正常工作,您需要将其添加到您的 AndroidManifest.xml 文件中。

解决方案:

像这样将这个RoomViewModel 类添加到您的AndroidManifest.xml 文件中。

<application
    android:name=".view.RoomViewModel"
    android:allowBackup="true" 

正如您在上面看到的,我们将其作为应用程序标签的名称属性。 这将修复您的空指针异常。但是您的程序将再次崩溃,因为您正在使用 Kotlin 并且确实使用 kotlin 腾出空间,这需要在您的应用程序级别的 build.gradle 文件中添加。

kapt "android.arch.persistence.room:compiler:1.1.1"

将其添加到依赖项块内的应用级别 build.gradle 之后。同步您的项目并运行它应该可以工作。

如果您想了解更多有关 Android 房间数据库的信息,可以查看此Room Database Tutorial。

希望这会对您有所帮助。

【讨论】:

  • But your program will again crash, because you are using Kotlin and do make room work with kotlin this thing needs to be added in your app level build.gradle file OP 已经在他们的 build.gradle 文件中有 kapt 空间。那不是问题。 OP 确认,只需在清单中添加应用程序就足够了
  • 在我的情况下它崩溃了,但没有问题,因为它在你身边工作。酷
  • 我实际上还必须将我的一个依赖项更改为 kapt 以纠正所有错误(只是忘记在我的评论中提及它)。毕竟,贝拉尔是对的,你们的意见都是正确的:D
猜你喜欢
  • 1970-01-01
  • 2022-01-01
  • 1970-01-01
  • 2020-11-28
  • 2019-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多