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表示这是项目mycalculation下data相关的类。
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 数据库的创建和版本升级。
- 它会帮你自动调用
onCreate和onUpgrade。
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,类级别变量/方法。 - 在整个类中可以直接访问,不需要实例化对象。
- 相当于 Java 中的
-
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 创建表语句:
sqlCREATE TABLE users( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE, password TEXT )- id → 自增主键
- username → 文本类型,唯一约束
- password → 文本类型
-
-
db.execSQL(createTableQuery)
- 执行 SQL 语句,创建表。
💡 小知识:
-
Kotlin 字符串拼接:
"Hello " + name或使用 模板字符串更推荐:kotlinval 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→ 新的版本号
方法内部逻辑
-
db.execSQL("DROP TABLE IF EXISTS $TABLE_USERS")- 执行 SQL 语句删除表
users(如果存在的话)。 $TABLE_USERS是 Kotlin 字符串模板 ,等价于"users"。- 目的是保证升级时重新创建表,避免表结构冲突。
- 执行 SQL 语句删除表
-
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→ 插入失败(例如用户名已存在)
详细拆解
- 获取可写数据库对象
kotlin
val db = this.writableDatabase
this→ 当前的UserDatabaseHelper对象writableDatabase→ 获取 可写数据库(如果数据库不存在会自动创建)- 后续所有操作都基于
db对象进行
- 准备数据
kotlin
val contentValues = ContentValues()
contentValues.put(COLUMN_USERNAME, username)
contentValues.put(COLUMN_PASSWORD, password)
-
ContentValues是 Android 提供的容器,用于存储 键值对(列名 → 数据) -
.put()方法可以放入不同类型数据(字符串、整数、布尔等) -
最终数据长这样:
{ "username": "Tom", "password": "123456" }
- 插入数据
kotlin
val result = db.insert(TABLE_USERS, null, contentValues)
-
insert(tableName, nullColumnHack, values)- tableName → 表名
- nullColumnHack → 当
values为空时指定列名(这里不需要,用 null) - values → 要插入的数据
-
返回值:
- 如果成功 → 返回新插入行的 ID(Long 类型)
- 如果失败 → 返回 -1
- 因此
return result != -1L就能判断是否成功
- 关闭数据库
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→ SQLWHERE子句,?是占位符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方法参数:- table → 表名
- columns → 查询列
- selection → 条件
- selectionArgs → 条件值
- groupBy → 分组(这里不用,填 null)
- having → 分组条件(不用,null)
- 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 的区别
-
查询条件不同:
kotlin"$COLUMN_USERNAME = ?"- 只匹配用户名,不需要密码
-
用法场景不同:
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 亮点总结
-
字符串模板
kotlin"$COLUMN_USERNAME = ?" -
数组字面量
kotlinval columns = arrayOf(COLUMN_ID) val selectionArgs = arrayOf(username, password) -
简洁的布尔返回
kotlinreturn count > 0
💡 小技巧:
- 可以把
checkUser改成只查询一行,效率更高:
kotlin
cursor.moveToFirst()
return cursor.count > 0
- 对于用户表小数据量,差别不大,但大型表建议优化。