You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Studio中如何管理Room每日问卷数据,避免单表堆积?

健身APP问卷数据存储管理方案

一、优化Room数据库表结构

当前单表堆积所有问卷数据会导致冗余高、查询效率低,建议拆分为两张关联表:

  • QuestionnaireRecord表:存储每次提交的元数据,核心字段示例:
    id INTEGER PRIMARY KEY AUTOINCREMENT, submit_time DATETIME NOT NULL, user_id INTEGER DEFAULT 0
    用来标记每一次提交的唯一记录、提交时间(精确到秒,区分每日3次提交)、所属用户ID(多用户场景可用)。
  • QuestionAnswer表:存储单题答案,关联问卷记录,核心字段示例:
    id INTEGER PRIMARY KEY AUTOINCREMENT, record_id INTEGER NOT NULL, question_no INTEGER NOT NULL, answer_content TEXT NOT NULL
    同时添加外键约束:FOREIGN KEY(record_id) REFERENCES QuestionnaireRecord(id) ON DELETE CASCADE,确保删除提交记录时自动删除对应题目答案。

拆分后优势:

  • 避免重复存储提交时间等元数据,减少冗余
  • 查询某一次提交的所有答案时,通过record_id关联即可,逻辑清晰
  • 后续统计单题答案分布、时间段提交记录等操作效率更高

二、数据导出与可视化准备

1. 导出完整SQLite数据库文件

无需每次导出SQL脚本,直接复制Room对应的SQLite数据库文件(路径通常为/data/data/[你的APP包名]/databases/)到指定目录即可,后续用SQLite可视化工具(如DB Browser for SQLite)直接打开分析,或导出为CSV/Excel格式做可视化。

APP内一键导出的工具类示例(Kotlin):

fun exportDatabase(context: Context) {
    val dbFile = context.getDatabasePath("your_database_name.db")
    val targetDir = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), "FitnessAppData")
    if (!targetDir.exists()) targetDir.mkdirs()
    val targetFile = File(targetDir, "fitness_data_${System.currentTimeMillis()}.db")

    try {
        FileInputStream(dbFile).use { input ->
            FileOutputStream(targetFile).use { output ->
                input.copyTo(output)
            }
        }
        // 这里可添加导出成功的UI提示
    } catch (e: IOException) {
        e.printStackTrace()
        // 处理导出失败逻辑
    }
}

注意:Android 13及以上需申请对应存储权限,可根据系统版本动态申请MANAGE_EXTERNAL_STORAGE或媒体读写权限。

2. 按需导出统计数据

如果仅需分析特定维度数据,可直接在APP内编写查询逻辑,将结果导出为CSV文件,方便可视化工具直接读取:

fun exportAnswersToCsv(context: Context, startDate: String, endDate: String) {
    val db = Room.databaseBuilder(context, AppDatabase::class.java, "your_database_name").build()
    val answerDao = db.questionAnswerDao()
    val recordDao = db.questionnaireRecordDao()
    
    val records = recordDao.getRecordsByDateRange(startDate, endDate)
    val targetDir = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), "FitnessAppData")
    if (!targetDir.exists()) targetDir.mkdirs()
    val targetFile = File(targetDir, "answers_$startDate-$endDate.csv")

    FileWriter(targetFile).use { writer ->
        // 写入CSV表头
        writer.append("提交时间,题目编号,答案\n")
        records.forEach { record ->
            val answers = answerDao.getAnswersByRecordId(record.id)
            answers.forEach { answer ->
                writer.append("${record.submitTime},${answer.questionNo},${answer.answerContent}\n")
            }
        }
    }
    db.close()
}

三、日常数据维护

  • 自动清理旧数据:在APP内添加清理功能,允许用户删除N天前的历史数据,避免数据库膨胀。例如执行SQL:DELETE FROM QuestionnaireRecord WHERE submit_time < '2024-01-01',通过外键的ON DELETE CASCADE配置,关联的题目答案会自动删除。
  • 添加索引优化:在QuestionnaireRecord的submit_time字段、QuestionAnswer的record_id和question_no字段添加索引,提升查询速度:
    CREATE INDEX idx_submit_time ON QuestionnaireRecord(submit_time);
    CREATE INDEX idx_record_id ON QuestionAnswer(record_id);
    CREATE INDEX idx_question_no ON QuestionAnswer(question_no);
    

内容的提问来源于stack exchange,提问作者jeremy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 12:20:22