You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin Android应用点击提交按钮崩溃问题排查(SQLite后端)

问题描述

我正在开发一款Android应用,核心功能为输入邮箱与密码后验证用户是否存在,但点击提交按钮后应用立即崩溃。重新创建新应用后该问题仍持续存在,希望排查崩溃原因。

相关代码

XML布局文件

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/editTextTextEmailAddress"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:ems="10"
        android:inputType="textEmailAddress"
        app:layout_constraintBottom_toTopOf="@+id/editTextTextPassword"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.497"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.554" />

    <EditText
        android:id="@+id/editTextTextPassword"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="448dp"
        android:ems="10"
        android:inputType="textPassword"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.502"
        app:layout_constraintStart_toStartOf="parent" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/editTextTextPassword"
        app:layout_constraintVertical_bias="0.145" />
</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity代码

package com.example.myapplication
import MyDatabaseHelper
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.Toast

class MainActivity : AppCompatActivity() {
    private lateinit var dbHelper: MyDatabaseHelper
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        var email=findViewById<EditText>(R.id.editTextTextEmailAddress)
        var password=findViewById<EditText>(R.id.editTextTextPassword)
        var submit=findViewById<Button>(R.id.button)
        submit.setOnClickListener{
            if(isUserExists(email.text.toString(),password.text.toString())){
                Toast.makeText(this,"Yes it okay",Toast.LENGTH_LONG)
            }
            else{
                Toast.makeText(this,"Yes it not okay",Toast.LENGTH_LONG)
            }
        }
    }
    private fun isUserExists(email: String, password: String): Boolean {
        val db = dbHelper.readableDatabase
        val cursor = db.query("user_credentials", null, "email=? AND password=?",arrayOf(email, password), null, null, null
        )
        val count = cursor .count
        cursor. close()
        return count > 0
    }
}

数据库助手类代码

import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import android.content.Context

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

    companion object {
        private const val DATABASE_NAME = "my_database.db"
        private const val DATABASE_VERSION = 1

        private const val TABLE_NAME = "user_credentials"
        private const val COLUMN_ID = "_id"
        private const val COLUMN_EMAIL = "email"
        private const val COLUMN_PASSWORD = "password"

        private const val SQL_CREATE_TABLE =
            "CREATE TABLE $TABLE_NAME (" +
                    "$COLUMN_ID INTEGER PRIMARY KEY AUTOINCREMENT, " +
                    "$COLUMN_EMAIL TEXT, " +
                    "$COLUMN_PASSWORD TEXT)"

        // Add constant for password hashing algorithm, if needed
        // private const val PASSWORD_HASH_ALGORITHM = "SHA-256"
    }

    override fun onCreate(db: SQLiteDatabase) {
        db.execSQL(SQL_CREATE_TABLE)
    }

    override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
        // Placeholder for database upgrade logic
        // Example: If you need to add new columns or modify table structure,
        // you can handle the upgrade here by dropping and recreating the table,
        // or by migrating data as needed.
        // You can also implement version-specific upgrade steps based on oldVersion and newVersion.
    }

    // Add method for password hashing, if needed
    // private fun hashPassword(password: String): String {
    //     // Implement password hashing logic here
    // }
}

崩溃原因分析

  1. 未初始化数据库助手实例:你声明了private lateinit var dbHelper: MyDatabaseHelper,但在onCreate方法中没有对dbHelper进行初始化。当点击按钮调用isUserExists方法时,会尝试访问未初始化的dbHelper,触发UninitializedPropertyAccessException,直接导致应用崩溃。
  2. Toast未调用show()方法:即使解决了数据库的问题,你的Toast也不会显示,因为只调用了Toast.makeText()但没有链式调用.show()。

修复方案

修改MainActivity的onCreate方法,初始化dbHelper,同时补全Toast的show()调用:

package com.example.myapplication
import MyDatabaseHelper
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.Toast

class MainActivity : AppCompatActivity() {
    private lateinit var dbHelper: MyDatabaseHelper
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        // 初始化dbHelper
        dbHelper = MyDatabaseHelper(this)
        
        var email=findViewById<EditText>(R.id.editTextTextEmailAddress)
        var password=findViewById<EditText>(R.id.editTextTextPassword)
        var submit=findViewById<Button>(R.id.button)
        submit.setOnClickListener{
            if(isUserExists(email.text.toString(),password.text.toString())){
                Toast.makeText(this,"用户存在",Toast.LENGTH_LONG).show()
            }
            else{
                Toast.makeText(this,"用户不存在",Toast.LENGTH_LONG).show()
            }
        }
    }
    private fun isUserExists(email: String, password: String): Boolean {
        val db = dbHelper.readableDatabase
        val cursor = db.query("user_credentials", null, "email=? AND password=?",arrayOf(email, password), null, null, null
        )
        val count = cursor.count
        cursor.close()
        return count > 0
    }
}

额外注意事项

  • 密码存储安全:当前代码直接存储明文密码,这是严重的安全问题。建议在存储前对密码进行哈希处理(比如使用SHA-256或更安全的算法),验证时也比对哈希值而非明文。
  • 空值处理:可以添加输入校验,防止邮箱或密码为空时执行数据库查询,避免不必要的异常。

内容的提问来源于stack exchange,提问作者Shaleen Shukla

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 00:05:56