概念设计与规划
在写任何代码之前,清晰的规划是成功的关键。

(图片来源网络,侵删)
App 核心目标
我们的App名为“心语日记”(暂定),它的核心目标是帮助用户记录、识别和管理自己的情绪,并通过一些引导和回顾,提升用户的情绪认知和心理健康。
核心功能模块
- 情绪记录:用户可以快速记录当下的情绪状态。
- 情绪识别与分析:通过用户输入的文字或选择,智能分析情绪倾向。
- 情绪日历与历史:以日历形式展示用户过去的情绪轨迹。
- 情绪洞察与回顾:定期生成周报/月报,总结情绪模式和触发点。
- 正念练习与引导:提供一些简单的呼吸练习、感恩日记等小工具。
目标用户
- 希望了解自己情绪模式的年轻人。
- 感到压力、焦虑,需要情绪出口的用户。
- 对心理学、正念冥想感兴趣的初学者。
第二步:技术选型与架构
对于一款功能相对清晰的个人App,我们可以选择成熟且高效的现代安卓开发技术栈。
- 开发语言: Kotlin (官方推荐,更安全、简洁)
- UI 框架: Jetpack Compose (现代声明式UI库,代码量少,性能好,是未来趋势)
- 架构模式: MVVM (Model-View-ViewModel)
- Model: 数据层,负责处理数据来源(本地数据库、网络API)。
- View: UI层,即我们的Jetpack Compose界面,负责展示和接收用户输入。
- ViewModel: 业务逻辑层,作为View和Model之间的桥梁,处理UI逻辑,持有并暴露UI所需的数据。
- 数据库: Room (一个强大的SQLite抽象层,可以轻松保存和查询数据)
- 依赖注入: Hilt (Google官方推荐,用于管理对象的生命周期,使代码更解耦)
- 异步处理: Kotlin Coroutines (用于处理耗时操作,如网络请求、数据库读写,避免界面卡顿)
第三步:核心功能模块实现详解
我们将以“情绪记录”和“情绪历史”这两个核心功能为例,讲解具体的实现思路。
情绪记录
目标: 用户打开页面,选择或输入情绪,并保存。

(图片来源网络,侵删)
数据模型 (Model - data class)
我们需要定义一个数据类来表示一条情绪记录。
// data/MoodEntry.kt
import androidx.room.Entity
import androidx.room.PrimaryKey
import java.util.Date
@Entity(tableName = "mood_entries")
data class MoodEntry(
@PrimaryKey(autoGenerate = true)
val id: Int = 0,
val moodType: String, // "happy", "sad", "angry", "anxious"
val note: String, // 用户输入的备注
val timestamp: Date // 记录的时间
)
这里使用了 Room 的 @Entity 注解,表示这个类会对应数据库中的一张表。
数据库访问层 (Model - DAO & Database) 我们需要一个接口来操作数据库。
// dao/MoodEntryDao.kt
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import kotlinx.coroutines.flow.Flow // Flow用于实时观察数据变化
@Dao
interface MoodEntryDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertMoodEntry(entry: MoodEntry)
@Query("SELECT * FROM mood_entries ORDER BY timestamp DESC")
fun getAllMoodEntries(): Flow<List<MoodEntry>> // 返回一个Flow,UI可以订阅它
}
配置 RoomDatabase。

(图片来源网络,侵删)
// database/AppDatabase.kt
import androidx.room.Database
import androidx.room.RoomDatabase
@Database(entities = [MoodEntry::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun moodEntryDao(): MoodEntryDao
}
ViewModel (业务逻辑) ViewModel负责处理UI的请求,并从数据库获取数据。
// viewModel/MoodViewModel.kt
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel // 使用Hilt注入依赖
class MoodViewModel @Inject constructor(
private val moodEntryDao: MoodEntryDao // Hilt会自动提供这个Dao的实例
) : ViewModel() {
// 使用Flow来暴露数据给UI
val allMoodEntries = moodEntryDao.getAllMoodEntries()
// 保存新情绪记录的函数
fun addMoodEntry(moodType: String, note: String) {
viewModelScope.launch { // 在协程中执行耗时操作
val newEntry = MoodEntry(
moodType = moodType,
note = note,
timestamp = Date()
)
moodEntryDao.insertMoodEntry(newEntry)
}
}
}
UI (View - Jetpack Compose) 我们用Compose来构建界面。
// ui/MoodRecordScreen.kt
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel // 方便获取ViewModel
import java.text.SimpleDateFormat
import java.util.*
@Composable
fun MoodRecordScreen(viewModel: MoodViewModel = hiltViewModel()) {
// 使用remember和mutableState来管理UI状态
var selectedMood by remember { mutableStateOf("happy") }
var noteText by remember { mutableStateOf("") }
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
Text(text = "今天感觉如何?", style = MaterialTheme.typography.headlineMedium)
// 情绪选择器 - 这里用简单的按钮代替
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
listOf("开心 😊", "难过 😢", "生气 😠", "焦虑 😰").forEach { mood ->
Button(onClick = { selectedMood = mood.split(" ")[0] }) {
Text(text = mood)
}
}
}
// 备注输入框
OutlinedTextField(
value = noteText,
onValueChange = { noteText = it },
label = { Text("可以写点什么...") },
modifier = Modifier.fillMaxWidth()
)
// 保存按钮
Button(
onClick = {
viewModel.addMoodEntry(selectedMood, noteText)
// 保存后清空输入
noteText = ""
},
modifier = Modifier.fillMaxWidth()
) {
Text(text = "记录心情")
}
}
}
情绪历史日历
目标: 以日历形式展示每天的情绪,点击可查看详情。
UI (View - Jetpack Compose)
这个功能更侧重于UI展示,我们可以使用一个第三方库,androidx.compose.material3:material3-calendar-compose,来快速构建日历。
// ui/MoodHistoryScreen.kt
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.hilt.navigation.compose.hiltViewModel
import java.text.SimpleDateFormat
import java.util.*
@Composable
fun MoodHistoryScreen(viewModel: MoodViewModel = hiltViewModel()) {
// 从ViewModel获取所有记录
val moodEntries by viewModel.allMoodEntries.collectAsState(initial = emptyList())
// 将记录按日期分组,用于日历显示
val moodMap = moodEntries.groupBy {
SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(it.timestamp)
}
Column(modifier = Modifier.fillMaxSize().padding(16.dp)) {
Text(text = "心情日历", style = MaterialTheme.typography.headlineMedium)
// 这里使用一个假设的Calendar组件
// 实际开发中,你需要引入一个日历库
SimpleCalendar(
modifier = Modifier.weight(1f),
moodMap = moodMap,
onDateClick = { date ->
// 点击日期后,可以弹出一个对话框显示当天的所有记录
// TODO: 实现详情对话框
}
)
}
}
// 这是一个简化的日历UI示意,实际开发请使用专业库
@Composable
fun SimpleCalendar(modifier: Modifier, moodMap: Map<String, List<MoodEntry>>, onDateClick: (Date) -> Unit) {
Box(modifier = modifier, contentAlignment = Alignment.Center) {
