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 // } }
崩溃原因分析
- 未初始化数据库助手实例:你声明了
private lateinit var dbHelper: MyDatabaseHelper,但在onCreate方法中没有对dbHelper进行初始化。当点击按钮调用isUserExists方法时,会尝试访问未初始化的dbHelper,触发UninitializedPropertyAccessException,直接导致应用崩溃。 - 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
相关产品推荐
相关产品推荐

