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 ---")
}
相关推荐
饭小猿人15 小时前
Android 腾讯X5WebView如何禁止系统自带剪切板和自定义剪切板视图
android·java
_李小白16 小时前
【android opencv学习笔记】Day 8: remap(像素位置重映射)
android·opencv·学习
美狐美颜SDK开放平台16 小时前
多场景美颜SDK解决方案:直播APP(iOS/安卓)开发接入详解
android·人工智能·ios·音视频·美颜sdk·第三方美颜sdk·短视频美颜sdk
嗷o嗷o16 小时前
Android BLE 里,MTU、分包和长数据发送到底该怎么处理
android
胡致和16 小时前
配置变更后,弹窗为什么飞到了最左边?
kotlin
Gary Studio18 小时前
Android AIDL HAL工程结构示例
android
y = xⁿ18 小时前
MySQL八股知识合集
android·mysql·adb
andr_gale19 小时前
04_rc文件语法规则
android·framework·aosp
祖国的好青年20 小时前
VS Code 搭建 React Native 开发环境(Windows 实战指南)
android·windows·react native·react.js