Android 下用kotlin写一个sqlite

复制代码
package com.example.myapplication

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import android.content.ContentValues
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import android.util.Log
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsPressedAsState
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.OutlinedTextFieldDefaults
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.runtime.getValue
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.material3.Surface
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue

import com.example.myapplication.printDatabase
import com.example.myapplication.ui.theme.MyApplicationTheme
import kotlinx.coroutines.delay
import kotlin.collections.addAll
import kotlin.text.clear

// 数据类,表示数据库中的一个项目
data class Item(val id: Int? = null, val name: String, val description: String)

// 数据库帮助类,用于管理数据库的创建、升级和数据操作
class DatabaseHelper(context: Context) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) {

    companion object {
        private const val DATABASE_NAME = "item_database" // 数据库名称
        private const val DATABASE_VERSION = 1 // 数据库版本
        private const val TABLE_NAME = "items" // 表名
        private const val COLUMN_ID = "id" // ID 列名
        private const val COLUMN_NAME = "name" // 名称列名
        private const val COLUMN_DESCRIPTION = "description" // 描述列名
    }
    // 创建数据库表
    override fun onCreate(db: SQLiteDatabase) {
        val createTableQuery = "CREATE TABLE $TABLE_NAME ($COLUMN_ID INTEGER PRIMARY KEY AUTOINCREMENT, $COLUMN_NAME TEXT, $COLUMN_DESCRIPTION TEXT)"
        db.execSQL(createTableQuery)
    }
    // 升级数据库表
    override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
        val dropTableQuery = "DROP TABLE IF EXISTS $TABLE_NAME"
        db.execSQL(dropTableQuery)
        onCreate(db)
    }
    // 插入一个项目
    fun insertItem(item: Item) {
        val db = writableDatabase
        val values = ContentValues().apply {
            put(COLUMN_NAME, item.name)
            put(COLUMN_DESCRIPTION, item.description)
        }
        db.insert(TABLE_NAME, null, values)
        db.close()
    }
    // 获取所有项目
    fun getAllItems(): List<Item> {
        val db = readableDatabase
        val query = "SELECT * FROM $TABLE_NAME"
        val cursor = db.rawQuery(query, null)
        val items = mutableListOf<Item>()

        if (cursor.moveToFirst()) {
            do {
                val id = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_ID))
                val name = cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_NAME))
                val description = cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DESCRIPTION))
                items.add(Item(id, name, description))
            } while (cursor.moveToNext())
        }

        cursor.close()
        db.close()
        return items
    }
    // 删除一个项目
    fun deleteItem(itemId: Int) {
        val db = writableDatabase
        db.delete(TABLE_NAME, "$COLUMN_ID=?", arrayOf(itemId.toString()))
        db.close()
    }
}

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            MyApplicationTheme {
                /*
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ){
                    Surface(
                        color = MaterialTheme.colorScheme.primary,
                        modifier = Modifier.padding(vertical = 25.dp, horizontal = 8.dp)
                    ) {
                        MainScreen()
                    }
                }*/
                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                    Surface(
                        color = MaterialTheme.colorScheme.primary,
                        modifier = Modifier.padding(innerPadding)
                    ) {
                        MainScreen()
                    }
                }
            }
        }
    }
}

@Composable
fun MainScreen() {
    val context = LocalContext.current
    val dbHelper = remember { DatabaseHelper(context) } // 记住数据库帮助类实例
    var itemName by remember { mutableStateOf("") } // 项目名称输入框的值
    var itemDescription by remember { mutableStateOf("") } // 项目描述输入框的值
    val items = remember { mutableStateListOf<Item>() } // 存储项目列表
    val showDatabaseContent = remember { mutableStateOf(false) } // 是否显示数据库内容的标志

    // 创建一个 MutableInteractionSource 来跟踪按钮的交互状态
    val interactionSource = remember { MutableInteractionSource() }

    // 获取按钮是否被按下的状态
    val isPressed by interactionSource.collectIsPressedAsState()

    // 根据按钮是否被按下,选择不同的颜色
    val buttonColor = if (isPressed) {
        Color(0xFF87CEEB) // 按下时的颜色 (更深的蓝色)
    } else {
        Color(0xFFADD8E6) // 默认颜色 (浅蓝色)
    }

    items.addAll(dbHelper.getAllItems()) // 初始化时从数据库加载数据

    Column(modifier = Modifier.padding(1.dp)) {
        // 项目名称输入框
        OutlinedTextField(
            value = itemName,
            onValueChange = { itemName = it },
            label = { Text("项目名称") },
            modifier = Modifier
                .fillMaxWidth()
                .padding(1.dp),
            colors = OutlinedTextFieldDefaults.colors(
                focusedTextColor = Color.Black, // 获得焦点时的文本颜色
                unfocusedTextColor = Color.Black, // 未获得焦点时的文本颜色
                focusedLabelColor = Color.Blue, // 获得焦点时的标签颜色
                unfocusedLabelColor = Color.Black, // 未获得焦点时的标签颜色
                cursorColor = Color.Black, // 光标颜色
                focusedBorderColor = Color.Blue, // 获得焦点时的边框颜色
                unfocusedBorderColor = Color.Gray, // 未获得焦点时的边框颜色
                //disabledBorderColor = Color.Gray, //禁用时的边框颜色
                //errorBorderColor = Color.Red, // 错误时的边框颜色
            )
        )
        // 项目描述输入框
        OutlinedTextField(
            value = itemDescription,
            onValueChange = { itemDescription = it },
            label = { Text("项目描述") },
            modifier = Modifier
                .fillMaxWidth()
                .padding(1.dp),
            colors = OutlinedTextFieldDefaults.colors(
                focusedTextColor = Color.Black, // 获得焦点时的文本颜色
                unfocusedTextColor = Color.Black, // 未获得焦点时的文本颜色
                focusedLabelColor = Color.Blue, // 获得焦点时的标签颜色
                unfocusedLabelColor = Color.Black, // 未获得焦点时的标签颜色
                cursorColor = Color.Black, // 光标颜色
                focusedBorderColor = Color.Blue, // 获得焦点时的边框颜色
                unfocusedBorderColor = Color.Gray, // 未获得焦点时的边框颜色
                //disabledBorderColor = Color.Gray, //禁用时的边框颜色
                //errorBorderColor = Color.Red, // 错误时的边框颜色
            )
        )
        // 添加项目按钮
        /*
        Button(
            onClick = {
                val newItem = Item(name = itemName, description = itemDescription)
                dbHelper.insertItem(newItem) // 插入新项目到数据库
                items.clear() // 清空列表
                items.addAll(dbHelper.getAllItems()) // 重新从数据库加载数据
                itemName = "" // 清空输入框
                itemDescription = "" // 清空输入框
            },
            colors = ButtonDefaults.buttonColors(containerColor = Color(0xFFADD8E6)),
            modifier = Modifier.fillMaxWidth()
        ) {
            Text("添加项目")
        }
         */
        Button(
            onClick = {
                val newItem = Item(name = itemName, description = itemDescription)
                dbHelper.insertItem(newItem) // 插入新项目到数据库
                items.clear() // 清空列表
                items.addAll(dbHelper.getAllItems()) // 重新从数据库加载数据
                itemName = "" // 清空输入框
                itemDescription = "" // 清空输入框
            },
            colors = ButtonDefaults.buttonColors(containerColor = buttonColor), // 使用动态的按钮颜色
            modifier = Modifier.fillMaxWidth(),
            interactionSource = interactionSource // 将 interactionSource 传递给 Button
        ) {
            Text("添加项目")
        }



        // 显示/隐藏数据库按钮
        Button(
            onClick = {
                showDatabaseContent.value = !showDatabaseContent.value // 切换显示/隐藏状态
            },
            colors = ButtonDefaults.buttonColors(containerColor = Color(0xFFADD8E6)),
        ) {
            Text("显示/隐藏 数据库")
        }
        // 根据 showDatabaseContent 的值决定是否显示数据库内容
        if (showDatabaseContent.value) {
            DatabaseContentScreen(dbHelper) // 显示数据库内容
        }
        /*
        LazyColumn(modifier = Modifier.padding(16.dp)) {
            items(items) { item ->
                ItemRow(item = item)
            }
        }*/
    }
}

@Composable
fun ItemRow(item: Item) {
    Column(modifier = Modifier.padding(8.dp)) {
        Text(text = "Name: ${item.name}")
        Text(text = "Description: ${item.description}")
    }
}

// 数据库内容屏幕 Composable
@Composable
fun DatabaseContentScreen(dbHelper: DatabaseHelper) {
    // 使用 remember 记住从数据库获取的数据,并转换为可变列表
    val items = remember { dbHelper.getAllItems().toMutableList() }
    // 记住当前选中的项目,初始为 null
    var selectedItem by remember { mutableStateOf<Item?>(null) }
    // 创建一个 LazyListState,用于控制 LazyColumn 的滚动
    val lazyListState = rememberLazyListState()

    Column(modifier = Modifier.padding(16.dp)) {

        // 删除按钮
        Button(
            onClick = {
                selectedItem?.let {
                    dbHelper.deleteItem(it.id!!) // 从数据库删除
                    items.remove(it) // 从列表中移除
                    selectedItem = null // 清空选中项
                }
            },
            enabled = selectedItem != null, // 仅当有选中项时才启用
            colors = ButtonDefaults.buttonColors(containerColor = Color(0xFFADD8E6)),
            //modifier = Modifier.padding(top = 8.dp)
        ) {
            Text("删除选中项")
        }
        // 表头
        Row(modifier = Modifier
            .fillMaxWidth()
            .background(Color.LightGray)) {
            TableCell(text = "ID", weight = 0.1f, isHeader = true) // ID 列
            TableCell(text = "名称", weight = 0.4f, isHeader = true) // 名称列
            TableCell(text = "描述", weight = 0.5f, isHeader = true) // 描述列
        }

        // 表格行
        LazyColumn (
            state = lazyListState, // 将 LazyListState 绑定到 LazyColumn
            //reverseLayout = true // 设置反向布局,让列表从底部开始显示
        ){
            items(items) { item ->
                val isSelected = selectedItem?.id == item.id // 判断当前行是否被选中
                Row(
                    modifier = Modifier
                        .fillMaxWidth()
                        .clickable { selectedItem = if (isSelected) null else item } // 点击行时切换选中状态
                        .background(if (isSelected) Color.Cyan else Color.Transparent) // 根据选中状态改变背景色
                ) {
                    TableCell(text = item.id?.toString() ?: "", weight = 0.1f) // ID
                    TableCell(text = item.name, weight = 0.4f) // 名称
                    TableCell(text = item.description, weight = 0.5f) // 描述
                }
            }
        }
        // 使用 LaunchedEffect 在 items 改变时滚动到最底部
        LaunchedEffect(items) {
            if (items.isNotEmpty()) {
                //lazyListState.scrollToItem(0) // 滚动到索引为 0 的项目,因为是反向布局,所以是最后一条数据
                //lazyListState.scrollToItem(items.size - 1) // 滚动到最后一条数据
                lazyListState.scrollToItem(items.lastIndex) // 滚动到最后一项
            }
        }

    }
}

@Composable
fun TableCell(text: String, weight: Float, isHeader: Boolean = false) {
    Text(
        text = text,
        modifier = Modifier
            .padding(8.dp),
        fontWeight = if (isHeader) FontWeight.Bold else FontWeight.Normal
    )
}

fun printDatabase(dbHelper: DatabaseHelper) {
    val items = dbHelper.getAllItems()
    Log.d("DatabaseContent", "--- Database Content ---")
    for (item in items) {
        Log.d("DatabaseContent", "ID: ${item.id}, Name: ${item.name}, Description: ${item.description}")
    }
    Log.d("DatabaseContent", "--- End of Database Content ---")
}
相关推荐
蒸鱼Yuzheng2 小时前
设备端性能工件可靠导出:断点续传、哈希、manifest 与失败恢复
android·自动化测试·python·adb·数据完整性
美狐美颜sdk4 小时前
直播APP接入美颜SDK后出现卡顿怎么办?从性能瓶颈寻找解决方案
android·人工智能·音视频·美颜sdk·直播美颜sdk
美狐美颜SDK开放平台4 小时前
直播APP开发实战:从摄像头调用到视频美颜sdk集成
android·人工智能·计算机视觉·音视频·直播美颜sdk
alexhilton5 小时前
生命周期感知的多模块启动模式
android·kotlin·android jetpack
三少爷的鞋6 小时前
Android 架构指南:suspend 如何响应取消?别再给 Repository 加 `cancel()`
android
迪飞特科技7 小时前
【无标题】
android·人工智能·本地化大模型
FlightYe7 小时前
视界原理之2D视频(二):视频文件里有什么
android·linux·网络·c++·ffmpeg·音视频·aac
传奇开心果编程7 小时前
【Flutter入门练中学】第8课:动画与过渡
android·学习·flutter·ui·ios
传奇开心果编程9 小时前
【Flutter入门练中学】第11课:状态管理进阶与声明式路由
android·学习·flutter·ui·ios
JasonSJX10 小时前
四端自建播放器怎么落地:Android、iOS、tvOS、Tizen 的 DRM 播放 SDK 技术盘点
android·ios·音视频·视频防录屏·加密保护课程·直播安全