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

kotlin 复制代码
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️⃣ 包声明

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

2️⃣ 导入库

kotlin 复制代码
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 数据库的创建和版本升级。
    • 它会帮你自动调用 onCreateonUpgrade

3️⃣ 类声明

kotlin 复制代码
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(伴生对象)

kotlin 复制代码
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 方法

kotlin 复制代码
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 创建表语句:

      sql 复制代码
      CREATE TABLE users(
          id INTEGER PRIMARY KEY AUTOINCREMENT,
          username TEXT UNIQUE,
          password TEXT
      )
      • id → 自增主键
      • username → 文本类型,唯一约束
      • password → 文本类型
  • db.execSQL(createTableQuery)

    • 执行 SQL 语句,创建表。

💡 小知识:

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

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

⑥ onUpgrade 方法

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

作用

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

  • 参数:

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

方法内部逻辑

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

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

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

💡 注意:

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

⑦ addUser 方法

kotlin 复制代码
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 → 插入失败(例如用户名已存在)

详细拆解

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

  1. 准备数据
kotlin 复制代码
val contentValues = ContentValues()
contentValues.put(COLUMN_USERNAME, username)
contentValues.put(COLUMN_PASSWORD, password)
  • ContentValues 是 Android 提供的容器,用于存储 键值对(列名 → 数据)

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

  • 最终数据长这样:

    复制代码
    {
        "username": "Tom",
        "password": "123456"
    }

  1. 插入数据
kotlin 复制代码
val result = db.insert(TABLE_USERS, null, contentValues)
  • insert(tableName, nullColumnHack, values)

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

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

  1. 关闭数据库
kotlin 复制代码
db.close()
  • 操作完数据库一定要关闭,避免内存泄漏和锁表问题。

Kotlin 语法亮点

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

⑧ 使用示例

kotlin 复制代码
val dbHelper = UserDatabaseHelper(context)

// 尝试添加用户
val isAdded = dbHelper.addUser("Tom", "123456")
if (isAdded) {
    println("用户添加成功")
} else {
    println("用户名已存在")
}
  • 会自动检查用户名是否重复(因为 username 列是 UNIQUE
  • 如果重复 → insert 返回 -1 → 返回 false

⑨ checkUser 方法

kotlin 复制代码
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️⃣ 获取可读数据库
kotlin 复制代码
val db = this.readableDatabase
  • writableDatabase 不同,readableDatabase 是只读的
  • 查询数据用它就够了,效率更高

2️⃣ 指定查询的列
kotlin 复制代码
val columns = arrayOf(COLUMN_ID)
  • 查询列,这里只查 id 就够了,不需要拿出所有数据(密码、用户名)
  • 提高效率

3️⃣ 构造查询条件
kotlin 复制代码
val selection = "$COLUMN_USERNAME = ? AND $COLUMN_PASSWORD = ?"
val selectionArgs = arrayOf(username, password)
  • selection → SQL WHERE 子句,? 是占位符
  • selectionArgs → 占位符对应的实际值
  • SQL 实例:
sql 复制代码
SELECT id FROM users WHERE username = 'Tom' AND password = '123456';
  • 使用占位符可以防止 SQL 注入攻击

4️⃣ 执行查询
kotlin 复制代码
val cursor = db.query(
    TABLE_USERS,
    columns,
    selection,
    selectionArgs,
    null,
    null,
    null
)
  • query 方法参数:

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


5️⃣ 获取结果
kotlin 复制代码
val count = cursor.count
  • cursor.count → 查询到的行数
  • 如果大于 0,说明有匹配用户

6️⃣ 关闭资源
kotlin 复制代码
cursor.close()
db.close()
  • Cursor 和数据库 都要关闭,避免内存泄漏和锁表问题

7️⃣ 返回结果
kotlin 复制代码
return count > 0
  • 如果匹配行数 > 0 → 返回 true
  • 否则 → 返回 false

⑩ isUsernameExists 方法

kotlin 复制代码
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 的区别

  1. 查询条件不同:

    kotlin 复制代码
    "$COLUMN_USERNAME = ?"
    • 只匹配用户名,不需要密码
  2. 用法场景不同:

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

使用示例

kotlin 复制代码
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 亮点总结

  1. 字符串模板

    kotlin 复制代码
    "$COLUMN_USERNAME = ?"
  2. 数组字面量

    kotlin 复制代码
    val columns = arrayOf(COLUMN_ID)
    val selectionArgs = arrayOf(username, password)
  3. 简洁的布尔返回

    kotlin 复制代码
    return count > 0

💡 小技巧:

  • 可以把 checkUser 改成只查询一行,效率更高:
kotlin 复制代码
cursor.moveToFirst()
return cursor.count > 0
  • 对于用户表小数据量,差别不大,但大型表建议优化。

相关推荐
吾诺1 小时前
MySQL远程连接错误解决:“Host is not allowed to connect to this MySQL server”详解
数据库·mysql
常利兵1 小时前
打造Android网络框架:为请求铺就高速路
android·网络·php
xuansec2 小时前
【PortSwigger】SQL注入第一题:WHERE 子句注入漏洞利用 —— 检索隐藏数据
数据库·sql
艾莉丝努力练剑2 小时前
【MYSQL】MYSQL学习的一大重点:MYSQL数据类型
android·linux·数据库·人工智能·学习·mysql·网络安全
惶了个恐2 小时前
Linux系统编程第十弹——sqlite3
数据库
c++之路2 小时前
Ubuntu 22.04 完整安装与配置指南(VMware + 系统优化 + 开发环境)
linux·数据库·ubuntu
pangares2 小时前
MySQL中between and的基本用法
android·数据库·mysql
喵叔哟2 小时前
8. 【Blazor全栈开发实战指南】--路由与导航
数据库·微服务·.net
liqianpin12 小时前
maven导入spring框架
数据库·spring·maven