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
相关产品推荐
相关产品推荐

