使用 SQLite 数据库启动应用程序时出现 NullPointerException

NullPointerException on Application startup using SQLite database

我对 Kotlin 和 SQLite 比较陌生,我使用 android studio 制作的应用程序不断产生 NullPointerReference 错误。

我的应用程序从用户那里获取输入并将其存储到 SQLite 数据库中。然后它将条目加载到主页上。当 运行 我的应用程序第一次出现时,它会产生以下错误。

Logcat

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.reminders/com.example.reminders.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.File android.content.Context.getDatabasePath(java.lang.String)' on a null object reference
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3654)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3806)
        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:2267)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:237)
        at android.app.ActivityThread.main(ActivityThread.java:8167)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)
     Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.File android.content.Context.getDatabasePath(java.lang.String)' on a null object reference
        at android.content.ContextWrapper.getDatabasePath(ContextWrapper.java:337)
        at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:445)
        at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:415)
        at com.example.reminders.FeedReaderDbHelper.viewReminder(DatabaseHandler.kt:61)
        at com.example.reminders.HistoryActivity.getItemsList(HistoryActivity.kt:37)
        at com.example.reminders.HistoryActivity.setupListofDataintoRecyclerView(HistoryActivity.kt:20)
        at com.example.reminders.MainActivity.onCreate(MainActivity.kt:99)
        at android.app.Activity.performCreate(Activity.java:7963)
        at android.app.Activity.performCreate(Activity.java:7952)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1307)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3629)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3806) 
        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:2267) 
        at android.os.Handler.dispatchMessage(Handler.java:107) 
        at android.os.Looper.loop(Looper.java:237) 
        at android.app.ActivityThread.main(ActivityThread.java:8167) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100) 

来自我的 MainActivity 的相关代码

class MainActivity : AppCompatActivity() {

    lateinit var alarmService: AlarmService
    lateinit var historyActivity: HistoryActivity

    @RequiresApi(Build.VERSION_CODES.N)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
            setContentView(R.layout.history_main)
            createNotificationChannel()
            alarmService = AlarmService(this)
            historyActivity = HistoryActivity()
                                    
                            ...

    }
    historyActivity.setupListofDataintoRecyclerView(this)
}

启动时,我打算让它检查数据库中的项目数是否 > 0。如果大于 0,应用程序将加载数据库。没有则显示没有条目

来自我的 HistoryActivity 的相关代码

    fun setupListofDataintoRecyclerView(context: Context) {
        if (getItemsList().size > 0) {
            tvEmptyHistory.visibility = View.GONE
            rvHistory.visibility = View.VISIBLE
            rvHistory.layoutManager = LinearLayoutManager(context)
            var itemAdapter = HistoryAdapter(context, getItemsList())
            rvHistory.adapter = itemAdapter
        }
        else {
            tvEmptyHistory.visibility = View.VISIBLE
            rvHistory.visibility = View.GONE
        }
    }

    private fun getItemsList(): ArrayList<reminderHistory> {
        //create instance of DatabaseHandler
        val databaseHandler = FeedReaderDbHelper(this)
        //call method to view database
        return databaseHandler.viewReminder()
    }

来自我的 FeedReaderDbHelper 的相关代码 class

class FeedReaderDbHelper(context: Context) :
    SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) {

                            ...

    fun viewReminder(): ArrayList<reminderHistory> {
        val rHistList: ArrayList<reminderHistory> = ArrayList()
        val selectQuery = "SELECT * FROM $TABLE_CONTACTS"
        val db = this.readableDatabase
        var cursor: Cursor? = null

        try {
            cursor = db.rawQuery(selectQuery, null)
        } catch (e: SQLiteException) {
            db.execSQL(selectQuery)
            return ArrayList()
        }
        var id: Int
        var item: String
        var hour: Int
        var min: Int
        var date: String

        if (cursor.moveToFirst()) {
            do {
                id = cursor.getInt((cursor.getColumnIndex(KEY_ID)))
                item = cursor.getString(cursor.getColumnIndex(KEY_ITEM))
                hour = cursor.getInt(cursor.getColumnIndex(KEY_HOUR))
                min = cursor.getInt(cursor.getColumnIndex(KEY_MIN))
                date = cursor.getString(cursor.getColumnIndex(KEY_DATE))

                val reminder =
                    reminderHistory(id = id, item = item, hour = hour, min = min, date = date)
                rHistList.add(reminder)
            } while (cursor.moveToNext())
        }
        cursor.close()
        return rHistList
    }
                ...

下面的错误行

at com.example.reminders.FeedReaderDbHelper.viewReminder(DatabaseHandler.kt:61)

指的是行val db = this.readableDatabase

我不确定问题出在上下文为空(属于 class)还是数据库。 请就此提出任何建议或意见。 谢谢。

您以错误的方式调用 historyActivity,请尝试使用 intent 打开 activity。尝试使用以下代码实现。

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.history_main)
    createNotificationChannel()
    alarmService = AlarmService(this)
    val intent = Intent(this, HistoryActivity::class.java)
    startActivity(intent)
}