欢迎光临
我们一直在努力

Android开发:用户注册和登录的数据库代码详细解释

package com.example.mycalculation.data

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

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

companion object {
private const val DATABASE_NAME = "UserDatabase.db"
private const val DATABASE_VERSION = 1
private const val TABLE_USERS = "users"
private const val COLUMN_ID = "id"
private const val COLUMN_USERNAME = "username"
private const val COLUMN_PASSWORD = "password"
}

override fun onCreate(db: SQLiteDatabase) {
val createTableQuery = ("CREATE TABLE " + TABLE_USERS + "("
+ COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ COLUMN_USERNAME + " TEXT UNIQUE,"
+ COLUMN_PASSWORD + " TEXT" + ")")
db.execSQL(createTableQuery)
}

override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
db.execSQL("DROP TABLE IF EXISTS $TABLE_USERS")
onCreate(db)
}

/**
* 添加新用户
* @return 如果插入成功返回 true,如果用户名已存在返回 false
*/

fun addUser(username: String, password: String): Boolean {
val db = this.writableDatabase
val contentValues = ContentValues()
contentValues.put(COLUMN_USERNAME, username)
contentValues.put(COLUMN_PASSWORD, password)

val result = db.insert(TABLE_USERS, null, contentValues)
db.close()
return result != 1L
}

/**
* 验证用户登录
*/

fun checkUser(username: String, password: String): Boolean {
val db = this.readableDatabase
val columns = arrayOf(COLUMN_ID)
val selection = "$COLUMN_USERNAME = ? AND $COLUMN_PASSWORD = ?"
val selectionArgs = arrayOf(username, password)

val cursor = db.query(
TABLE_USERS,
columns,
selection,
selectionArgs,
null,
null,
null
)

val count = cursor.count
cursor.close()
db.close()

return count > 0
}

/**
* 检查用户名是否已存在
*/

fun isUsernameExists(username: String): Boolean {
val db = this.readableDatabase
val columns = arrayOf(COLUMN_ID)
val selection = "$COLUMN_USERNAME = ?"
val selectionArgs = arrayOf(username)

val cursor = db.query(
TABLE_USERS,
columns,
selection,
selectionArgs,
null,
null,
null
)

val count = cursor.count
cursor.close()
db.close()

return count > 0
}
}

这是一个用户注册和登录数据库,用Android内置的SQLite

1️⃣ 包声明

package com.example.mycalculation.data

  • 作用:定义这个 Kotlin 文件的包(package),类似于文件夹,用来组织代码。
  • Kotlin 中的包可以帮助你区分同名类,避免冲突。
  • 比如这里 com.example.mycalculation.data 表示这是项目 mycalculation 下 data 相关的类。

2️⃣ 导入库

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

  • ContentValues

    • 用于存放要插入数据库的键值对数据,比如 "username" -> "Tom"。
  • Context

    • Android 中非常重要的类,表示当前应用环境,通常用来访问数据库、文件、资源等。
  • SQLiteDatabase

    • 表示 SQLite 数据库对象,你可以通过它执行 SQL 语句(增删改查)。
  • SQLiteOpenHelper

    • 是一个帮助类,用来管理 SQLite 数据库的创建和版本升级。
    • 它会帮你自动调用 onCreate 和 onUpgrade。

3️⃣ 类声明

class UserDatabaseHelper(context: Context) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION)

  • class UserDatabaseHelper(context: Context)

    • 声明了一个类 UserDatabaseHelper,构造函数接收一个 Context。
  • : SQLiteOpenHelper(…)

    • 表示继承 SQLiteOpenHelper,也就是让这个类拥有 SQLite 管理能力。
  • context → 当前应用环境

  • DATABASE_NAME → 数据库文件名

  • null → 默认的 CursorFactory,一般不用改

  • DATABASE_VERSION → 数据库版本号,用于升级管理

总结:这行代码的意思是,我们创建一个名叫 UserDatabaseHelper 的类,它能管理数据库创建、升级等。


4️⃣ companion object(伴生对象)

companion object {
private const val DATABASE_NAME = "UserDatabase.db"
private const val DATABASE_VERSION = 1
private const val TABLE_USERS = "users"
private const val COLUMN_ID = "id"
private const val COLUMN_USERNAME = "username"
private const val COLUMN_PASSWORD = "password"
}

  • Kotlin 特有写法 companion object

    • 相当于 Java 中的 static,类级别变量/方法。
    • 在整个类中可以直接访问,不需要实例化对象。
  • const val

    • 常量,编译时确定,不会改变。
  • 作用:这里定义数据库相关信息和字段名,方便后续使用。


5️⃣ onCreate 方法

override fun onCreate(db: SQLiteDatabase) {
val createTableQuery = ("CREATE TABLE " + TABLE_USERS + "("
+ COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ COLUMN_USERNAME + " TEXT UNIQUE,"
+ COLUMN_PASSWORD + " TEXT" + ")")
db.execSQL(createTableQuery)
}

  • override

    • 表示重写父类 SQLiteOpenHelper 的方法。
  • onCreate(db: SQLiteDatabase)

    • 当数据库第一次被创建时调用。
    • 参数 db 是 SQLiteDatabase 对象,用它来执行 SQL 语句。
  • val createTableQuery = …

    • 拼接 SQL 创建表语句:

      CREATE TABLE users(
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      username TEXT UNIQUE,
      password TEXT
      )

      • id → 自增主键
      • username → 文本类型,唯一约束
      • password → 文本类型
  • db.execSQL(createTableQuery)

    • 执行 SQL 语句,创建表。

💡 小知识:

  • Kotlin 字符串拼接:"Hello " + name 或使用 模板字符串更推荐:

    val createTableQuery = "CREATE TABLE $TABLE_USERS (" +
    "$COLUMN_ID INTEGER PRIMARY KEY AUTOINCREMENT," +
    "$COLUMN_USERNAME TEXT UNIQUE," +
    "$COLUMN_PASSWORD TEXT)"


⑥ onUpgrade 方法

override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
db.execSQL("DROP TABLE IF EXISTS $TABLE_USERS")
onCreate(db)
}

作用

  • 当数据库版本号 (DATABASE_VERSION) 升高 时,这个方法会被自动调用。

  • 参数:

    • db → 数据库对象
    • oldVersion → 旧的版本号
    • newVersion → 新的版本号

方法内部逻辑

  • db.execSQL("DROP TABLE IF EXISTS $TABLE_USERS")

    • 执行 SQL 语句删除表 users(如果存在的话)。
    • $TABLE_USERS 是 Kotlin 字符串模板,等价于 "users"。
    • 目的是保证升级时重新创建表,避免表结构冲突。
  • onCreate(db)

    • 删除表后重新调用 onCreate 创建新表。
    • 保证数据库表结构是最新的。
  • 💡 注意:

    • 这种做法适合 开发阶段或数据不重要 的情况。
    • 真正上线项目时,通常要写迁移逻辑而不是直接删表,否则用户数据会丢失。

    ⑦ addUser 方法

    fun addUser(username: String, password: String): Boolean {
    val db = this.writableDatabase
    val contentValues = ContentValues()
    contentValues.put(COLUMN_USERNAME, username)
    contentValues.put(COLUMN_PASSWORD, password)

    val result = db.insert(TABLE_USERS, null, contentValues)
    db.close()
    return result != 1L
    }

    作用

    • 用于向 users 表插入一条新用户数据。
    • 返回 true → 插入成功
    • 返回 false → 插入失败(例如用户名已存在)

    详细拆解

  • 获取可写数据库对象
  • val db = this.writableDatabase

    • this → 当前的 UserDatabaseHelper 对象
    • writableDatabase → 获取 可写数据库(如果数据库不存在会自动创建)
    • 后续所有操作都基于 db 对象进行

  • 准备数据
  • val contentValues = ContentValues()
    contentValues.put(COLUMN_USERNAME, username)
    contentValues.put(COLUMN_PASSWORD, password)

    • ContentValues 是 Android 提供的容器,用于存储 键值对(列名 → 数据)

    • .put() 方法可以放入不同类型数据(字符串、整数、布尔等)

    • 最终数据长这样:

      {
      "username": "Tom",
      "password": "123456"
      }


  • 插入数据
  • val result = db.insert(TABLE_USERS, null, contentValues)

    • insert(tableName, nullColumnHack, values)

      • tableName → 表名
      • nullColumnHack → 当 values 为空时指定列名(这里不需要,用 null)
      • values → 要插入的数据
    • 返回值:

      • 如果成功 → 返回新插入行的 ID(Long 类型)
      • 如果失败 → 返回 -1
      • 因此 return result != -1L 就能判断是否成功

  • 关闭数据库
  • db.close()

    • 操作完数据库一定要关闭,避免内存泄漏和锁表问题。

    Kotlin 语法亮点

    • fun addUser(…) : Boolean → 定义函数并指定返回类型
    • 字符串模板 $COLUMN_USERNAME、$TABLE_USERS → 比拼接字符串更方便
    • result != -1L → Kotlin 的布尔表达式直接返回

    ⑧ 使用示例

    val dbHelper = UserDatabaseHelper(context)

    // 尝试添加用户
    val isAdded = dbHelper.addUser("Tom", "123456")
    if (isAdded) {
    println("用户添加成功")
    } else {
    println("用户名已存在")
    }

    • 会自动检查用户名是否重复(因为 username 列是 UNIQUE)
    • 如果重复 → insert 返回 -1 → 返回 false

    ⑨ checkUser 方法

    fun checkUser(username: String, password: String): Boolean {
    val db = this.readableDatabase
    val columns = arrayOf(COLUMN_ID)
    val selection = "$COLUMN_USERNAME = ? AND $COLUMN_PASSWORD = ?"
    val selectionArgs = arrayOf(username, password)

    val cursor = db.query(
    TABLE_USERS,
    columns,
    selection,
    selectionArgs,
    null,
    null,
    null
    )

    val count = cursor.count
    cursor.close()
    db.close()

    return count > 0
    }

    功能

    • 检查数据库中是否有 用户名 + 密码 匹配的用户
    • 用于 登录验证

    详细拆解

    1️⃣ 获取可读数据库

    val db = this.readableDatabase

    • 与 writableDatabase 不同,readableDatabase 是只读的
    • 查询数据用它就够了,效率更高

    2️⃣ 指定查询的列

    val columns = arrayOf(COLUMN_ID)

    • 查询列,这里只查 id 就够了,不需要拿出所有数据(密码、用户名)
    • 提高效率

    3️⃣ 构造查询条件

    val selection = "$COLUMN_USERNAME = ? AND $COLUMN_PASSWORD = ?"
    val selectionArgs = arrayOf(username, password)

    • selection → SQL WHERE 子句,? 是占位符
    • selectionArgs → 占位符对应的实际值
    • SQL 实例:

    SELECT id FROM users WHERE username = 'Tom' AND password = '123456';

    • 使用占位符可以防止 SQL 注入攻击

    4️⃣ 执行查询

    val cursor = db.query(
    TABLE_USERS,
    columns,
    selection,
    selectionArgs,
    null,
    null,
    null
    )

    • query 方法参数:

    • table → 表名
    • columns → 查询列
    • selection → 条件
    • selectionArgs → 条件值
    • groupBy → 分组(这里不用,填 null)
    • having → 分组条件(不用,null)
    • orderBy → 排序(不用,null)
    • 返回 Cursor 对象,可以遍历查询结果


    5️⃣ 获取结果

    val count = cursor.count

    • cursor.count → 查询到的行数
    • 如果大于 0,说明有匹配用户

    6️⃣ 关闭资源

    cursor.close()
    db.close()

    • Cursor 和数据库 都要关闭,避免内存泄漏和锁表问题

    7️⃣ 返回结果

    return count > 0

    • 如果匹配行数 > 0 → 返回 true
    • 否则 → 返回 false

    ⑩ isUsernameExists 方法

    fun isUsernameExists(username: String): Boolean {
    val db = this.readableDatabase
    val columns = arrayOf(COLUMN_ID)
    val selection = "$COLUMN_USERNAME = ?"
    val selectionArgs = arrayOf(username)

    val cursor = db.query(
    TABLE_USERS,
    columns,
    selection,
    selectionArgs,
    null,
    null,
    null
    )

    val count = cursor.count
    cursor.close()
    db.close()

    return count > 0
    }

    功能

    • 检查用户名是否已存在
    • 用于注册时避免重复用户名

    与 checkUser 的区别

  • 查询条件不同:

    "$COLUMN_USERNAME = ?"

    • 只匹配用户名,不需要密码
  • 用法场景不同:

    • checkUser → 登录验证
    • isUsernameExists → 注册前检查重复

  • 使用示例

    val dbHelper = UserDatabaseHelper(context)

    // 登录验证
    val canLogin = dbHelper.checkUser("Tom", "123456")
    if (canLogin) println("登录成功") else println("用户名或密码错误")

    // 注册验证
    val exists = dbHelper.isUsernameExists("Tom")
    if (exists) println("用户名已存在") else println("可以注册")


    11 Kotlin 亮点总结

  • 字符串模板

    "$COLUMN_USERNAME = ?"

  • 数组字面量

    val columns = arrayOf(COLUMN_ID)
    val selectionArgs = arrayOf(username, password)

  • 简洁的布尔返回

    return count > 0


  • 💡 小技巧:

    • 可以把 checkUser 改成只查询一行,效率更高:

    cursor.moveToFirst()
    return cursor.count > 0

    • 对于用户表小数据量,差别不大,但大型表建议优化。

    赞(0)
    未经允许不得转载:171主机测评 » Android开发:用户注册和登录的数据库代码详细解释
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址