跳到正文 ChatGPT 说 · Jimmy Huang's Blog
← Seminar Week 7 Summary 学习 › C6001 › 2026 S1 › FIT5046 Mobile and distributed computing systems › Week 7 Android Jetpack: Room › Seminar Week 7 Summary ChatGPT 说 ChatGPT 说 本页目录· 46 条 1. 本周 Seminar 总览 本周 FIT5046 Seminar 主要讲两件事: Android Room 本地数据库 和 Kotlin Coroutines 协程 。这两个主题不是分开的:老师反复说明,数据库访问属于比较慢、不可预测的 I/O 操作,如果直接放在 Android 的主线程 / UI 线程上运行,可能会卡住界面,所以 Room 必须和 coroutine、Flow、ViewModel 一起理解。资料依据包括 Week 7 Room 课件、Week 7 Coroutines 课件和课堂 transcript。
这周的核心不是单纯背代码,而是理解一个 Android app 里“数据如何从数据库流向界面,又如何从界面写回数据库”。可以把整体结构理解成:
UI / Composable
→ ViewModel
→ Repository
→ DAO
→ Room Database
→ Entity / SQLite Table
老师强调: UI 不应该直接访问 DAO 或 Entity ,中间必须通过 ViewModel 和 Repository 这类结构来隔离职责。这样做是为了让代码结构清楚、方便测试,也避免数据库操作直接影响 UI 线程。transcript 里老师用图书馆类比解释:数据库像图书馆,Entity 像书,DAO 像可以对书做的操作,Repository 像对外服务窗口,用户不能直接冲进书库乱拿书。
本周还穿插了很多 assignment 相关提醒。老师说 GitLab 是必须使用的,faculty 配置的 GitLab repository 才是 marking 会看的仓库;main/master branch 是最终版本,developer branches 可以有多个,但最终测试好的功能要 merge 到 main/master。老师还提醒 AI acknowledgement、英文提交、Git commit history 和个人贡献都会影响 assignment marking。
2. 核心知识点总结 知识点 1:Android Architecture:UI Layer、Data Layer、可选 Domain Layer 是什么:
Android app 通常分层理解:最上面是 UI Layer,负责显示界面和接收用户操作;中间可以有 Domain Layer,处理复杂业务逻辑;下面是 Data Layer,负责访问数据来源,例如本地 Room database、远程 API、传感器数据等。Room 课件第 3 页把这个结构画出来,并把 ViewModel 标成 UI state holder,把 Repository 和 data source 放在 Data Layer。
为什么重要:
如果所有代码都写在 MainActivity 或 Composable 里,app 很快会变乱。分层可以让每一层只做自己的事:UI 管显示,ViewModel 管界面状态,Repository 管数据来源,DAO 管数据库操作。
和本课程整体关系:
FIT5046 后面会继续讲 API、cloud database、distributed/mobile systems。Room 是本地数据源,Retrofit / API 是远程数据源,Repository 可以把这些数据源统一起来,所以这是后续内容的架构基础。
学生更容易理解的话:
不要让按钮直接去数据库里拿数据。按钮只告诉 ViewModel:“用户想新增/删除/更新数据。”ViewModel 再找 Repository,Repository 再找 DAO,DAO 才真正碰数据库。
知识点 2:Room 是什么:Android 本地持久化数据库方案 是什么:
Room 是 Android Jetpack 的 persistence library。它不是一个完全新的数据库,而是 SQLite 上面的一层抽象,让开发者更方便、更安全地访问本地关系型数据库。SQLite 负责底层数据存储,Room 让你用 Kotlin class、annotation 和 DAO 方法来操作数据。
本页目录 为什么重要:
没有 Room 的话,用户在 app 里输入的数据可能只存在内存里。老师现场演示说,如果不用 Room,切换页面、关闭 emulator 或重新打开 app 后,用户输入/编辑的数据会丢失。Room 的作用就是让这些数据“保存下来”。
和本课程整体关系:
移动应用经常需要本地保存用户数据,比如设置、历史记录、表单草稿、离线数据等。本课程 Assignment 2 / Assignment 4 需要 app 有真实功能,因此本地持久化是重要能力。
学生更容易理解的话:
Room 就像手机 app 自己的小仓库。用户今天输入的数据,不应该明天一打开 app 就没了,所以要把它放进这个小仓库。
知识点 3:Room 的 5 个核心组件:Entity、DAO、Database、Repository、ViewModel 是什么:
老师说本周要记住 Room 相关的 5 个概念:
Entity:定义数据库里的表。
DAO:定义可以对表做什么操作。
Database:创建 Room database 实例,管理版本和 migration。
Repository:对外提供数据访问接口,把 DAO 包装起来。
ViewModel:连接 UI 和 Repository,管理 UI state。
Room 课件第 6–15 页依次讲了 Entity、DAO、Database、Repository、ViewModel。
为什么重要:
这 5 个组件是写 Room app 的标准结构。Assignment 里如果你想保存数据,基本就要按这个结构写。
和本课程整体关系:
这体现了 Android app 的 data architecture。后面做 API、cloud database、sensor data 时,也会继续用类似“UI → ViewModel → Repository → Data Source”的思路。
学生更容易理解的话:
Entity 说“我要存什么”;DAO 说“我能怎么操作它”;Database 说“数据库怎么创建”;Repository 说“外面的人通过我来访问数据”;ViewModel 说“我负责把数据变成界面能用的状态”。
知识点 4:Entity:把 Kotlin class 映射成数据库表 是什么:
Entity 用 @Entity 标记。每个 Entity 对应数据库中的一张表。class name 默认就是 table name,也可以通过 tableName 自己指定。属性名默认就是 column name,也可以用 @ColumnInfo 指定。Subject 示例里有 uid 和 name,其中 uid 用 @PrimaryKey(autoGenerate = true) 自动生成。
为什么重要:
Entity 决定了数据库到底存什么字段。设计 Entity 时,其实就是在设计 app 的数据结构。
和本课程整体关系:
这和软件设计中的 entity model、ER diagram、data modelling 有关系。你在 Assignment 里要思考:哪些数据需要本地保存?每种数据有哪些字段?字段之间有什么关系?
学生更容易理解的话:
Entity 就是数据库表的“模板”。比如 Subject 表里每一行是一门课,每门课有 id 和 name。
知识点 5:DAO:定义 CRUD 操作 是什么:
DAO 是 Data Access Object,通常写成 interface,没有 properties,主要定义对数据库数据的操作。常见 annotation 包括:
@Insert
@Update
@Delete
@Query
这些对应 CRUD:Create、Read、Update、Delete。课件中的 SubjectDao 例子用 @Query("SELECT * FROM subjects") 返回 Flow<List<Subject>>,insert/update/delete 都写成 suspend fun。
为什么重要:
DAO 是真正告诉 Room “怎么查、怎么插、怎么删、怎么改”的地方。没有 DAO,Entity 只是表结构,不能操作数据。
和本课程整体关系:
Assignment 里如果你有任何本地数据,比如用户记录、收藏、任务、日志、历史结果,都需要 DAO 来定义操作。
学生更容易理解的话:
Entity 是“数据长什么样”,DAO 是“我能对这些数据做什么”。比如:新增一门课、删除一门课、查询所有课程。
知识点 6:@Query 和 SQL 参数 是什么:
@Query 里可以写 SQL,例如 SELECT、 UPDATE、 DELETE。Room 会在 compile time 检查 query,如果字段名写错,会编译失败,而不是等 app 运行时才崩。传参数时要用冒号 :,例如:
@Query("SELECT * FROM subjects WHERE code = :codeEntered")
课件第 9 页特别提到 query code 会在 compile time 被检查,参数前要加 colon。
为什么重要:
这可以减少运行时错误,也让数据库查询更可靠。
和本课程整体关系:
后面你可能要做搜索、筛选、按 ID 查找、按条件更新等功能,这些都离不开 @Query。
学生更容易理解的话:
@Query 就是你告诉数据库:“帮我找出符合这个条件的数据。”冒号 : 表示这里要接收函数传进来的变量。
知识点 7:Database class、Singleton、companion object、synchronized、@Volatile 是什么:
Room database class 必须是 RoomDatabase 的 abstract subclass,并用 @Database annotation 标记。它需要列出 entities、version、exportSchema,并提供一个 abstract function 返回 DAO。课件示例中使用 companion object 保存 INSTANCE,通过 getDatabase() 获取数据库实例,并用 synchronized(this) 确保同一时间只有一个 thread 创建实例,用 @Volatile 保证不同 thread 看到的 INSTANCE 是最新的。
为什么重要:
Room database 应该是 singleton,也就是整个 app 只创建一个 database instance。多个 database instance 同时打开可能导致资源浪费、数据不一致或线程问题。
和本课程整体关系:
这是移动系统里很典型的 resource management 和 thread-safety 问题。它不仅是 Room 的语法点,也和多线程、并发、系统资源管理有关。
学生更容易理解的话:
数据库就像一个仓库管理系统,不要每个人都开一个新的仓库系统。大家应该共用同一个系统,而且同一时间只能有一个人负责创建它。
知识点 8:Migration、version、exportSchema、fallbackToDestructiveMigration 是什么:
Room database 有 version。课件说 version 从 1 开始,如果数据库或表结构改变,需要增加 version。 exportSchema 默认是 true,用于保存 schema 支持版本控制和 migration;课件示例设置成 false,因为课堂例子不需要 versioning/migration。 fallbackToDestructiveMigration(true) 表示没有 migration 时可以直接 drop and recreate tables,也就是可能丢失旧数据。
为什么重要:
如果 app 已经有用户数据,你后来改了表结构,就涉及 migration。处理不好会丢数据或导致 app 崩溃。
和本课程整体关系:
Assignment 阶段可能数据量不大,migration 不是核心,但理解它有助于你知道真实 app 为什么不能随便改数据库 schema。
学生更容易理解的话:
你原来表里只有 name,后来想加 age,数据库结构变了。Migration 就是告诉 app:“旧数据怎么搬到新表结构里。”如果直接 destructive migration,就像把旧表删掉重新建,旧数据会没。
知识点 9:Repository:数据访问的包装层 是什么:
Repository 是一个 abstraction layer。它通过 SubjectDatabase.getDatabase(application).subjectDAO() 拿到 DAO,然后提供 wrapper methods,例如 insert()、 delete()、 update()。Repository 也会暴露 allSubjects: Flow<List<Subject>> 给 ViewModel。
为什么重要:
老师反复强调,不要让 UI 或 ViewModel 直接访问 Entity/DAO。Repository 把数据来源包装起来,以后即使数据来源变多,例如 Room + API + sensor,也可以统一管理。
和本课程整体关系:
移动与分布式系统常常同时有本地数据和远程数据。Repository 是把多个 data sources 整合起来的重要架构模式。
学生更容易理解的话:
Repository 就像服务台。用户不用知道书在哪个架子、怎么登记,只要找服务台。服务台再去找 DAO/数据库完成操作。
知识点 10:ViewModel:UI 和数据层之间的 state holder 是什么:
ViewModel 是 UI Layer 的 state holder。它保存和管理 UI-related data,并位于 UI 和 Repository 中间。课件中使用 AndroidViewModel,因为 Repository constructor 需要 Application 参数。ViewModel 通过 viewModelScope.launch(Dispatchers.IO) 调用 Repository 的 suspend function。
为什么重要:
UI 会因为屏幕旋转、页面切换、重组 recomposition 等情况变化。ViewModel 可以在这些变化中保存状态,并把 Room 数据共享给不同 composable。
和本课程整体关系:
这连接了前面学过的 Jetpack Compose UI state 和这周的 Room data persistence。Assignment 中多个 screen 共享数据时,ViewModel 很关键。
学生更容易理解的话:
ViewModel 像前台经理。界面问它:“现在要显示什么?”用户点按钮时,它安排后台去处理数据库,不让界面自己去碰数据库。
知识点 11:Android 主线程 / UI 线程规则 是什么:
Android app 启动时,系统会创建一个 main thread,也叫 UI thread。课件给出两条规则:
不要 block main/UI thread。
不要从 UI thread 之外访问 Android UI toolkit。
长时间任务,例如 network access、database operations,要放到 background / worker threads。
为什么重要:
如果你在主线程里做数据库或网络请求,app 可能卡住、按钮没反应、界面冻结,用户体验很差。
和本课程整体关系:
Mobile computing 关注 responsive UI。移动 app 不只是“功能能跑”,还要不卡、不阻塞、不乱更新 UI。
学生更容易理解的话:
主线程像收银台。收银台只负责快速接待用户,不能让它去仓库慢慢找货,否则后面所有顾客都排队卡住。
知识点 12:Coroutines:用协程处理慢任务 是什么:
Coroutine 是 Kotlin 的并发设计模式,用来简化 asynchronous programming。它可以暂停和恢复执行,不会 block thread。函数如果要在 coroutine 中被调用,可以声明为 suspend fun。课件用 DAO 的 suspend fun updateSubject(subject: Subject) 举例。
为什么重要:
Room 的 insert/update/delete 这些数据库 I/O 操作不能直接堵塞 UI thread,所以要用 suspend function 和 coroutine。
和本课程整体关系:
本周 Room 只是 coroutine 的一个应用场景。下周讲 Retrofit / API request 时,老师也说网络请求同样不可预测,也要 asynchronous。transcript 中老师明确提到 database access、network access、local file system access,以及任何运行时间不可控的任务,都应该用 asynchronous mode。
学生更容易理解的话:
Coroutine 就是把慢活交给后台工人做。UI 不用等它做完,可以继续响应用户。后台做完后,再把结果交回来。
知识点 13:Dispatchers:决定 coroutine 在哪里跑 是什么:
Coroutine dispatcher 决定 coroutine 用哪个 thread 或 thread pool 执行:
Dispatchers.Default:CPU-heavy tasks,例如复杂计算、parsing。
Dispatchers.IO:blocking I/O tasks,例如 Room database、network。
Dispatchers.Main:Android main thread,用于更新 UI。
withContext(...):临时切换 dispatcher。
课件第 7 页明确说 Room 和 network operations 应使用 Dispatchers.IO。
为什么重要:
不是所有 coroutine 都应该放在同一个地方跑。数据库和网络应该走 IO,UI 更新必须回 Main。
和本课程整体关系:
这是 Android 并发编程的基本规则。Assignment 中只要你有 Room、API、文件读取,就需要知道该用哪个 dispatcher。
学生更容易理解的话:
Dispatcher 就像分配工作岗位:计算工作给计算区,数据库/网络工作给后台 I/O 区,更新界面只能回前台 UI 区。
知识点 14:Coroutine Scope:决定 coroutine 活多久 是什么:
Coroutine scope 定义 coroutine 的生命周期和取消规则。课件讲了:
viewModelScope:ViewModel 被 cleared 时取消。
lifecycleScope:跟 Activity / LifecycleOwner 生命周期相关。
CoroutineScope:自定义 scope,需要手动 cancel。
GlobalScope:顶层 scope,风险较高,因为可能一直运行到 app process 被杀。
为什么重要:
后台任务如果不取消,可能导致 memory leak 或持续消耗资源。老师也提醒 background thread / daemon thread 容易被忘记,持续消耗资源。
和本课程整体关系:
移动设备资源有限,后台任务管理很重要。好的 app 不应该乱开后台任务。
学生更容易理解的话:
Scope 就是后台任务的“有效期”。ViewModelScope 就像“这个页面/数据管理器还活着,任务才继续;它没了,任务也该停”。
知识点 15:Flow:连续数据流,把 Room 更新推给 UI 是什么:
Suspend function 通常返回单个值;Flow 可以随时间 emit 多个值,是基于 coroutine 的异步数据流。Room 支持 DAO 返回 Flow<List<Subject>>,当数据库变化时自动 emit 新数据。UI 里可以用 collectAsState() 把 Flow 转成 Compose 可观察的 State。
为什么重要:
数据库数据不是只查一次就结束。用户新增、删除、更新后,UI 应该自动刷新。Flow 可以让数据变化持续流向 UI。
和本课程整体关系:
这连接了 Room database 和 Jetpack Compose state management。后面传感器数据、API 数据、实时数据也会用类似“数据流”的思路。
学生更容易理解的话:
Flow 就像订阅通知。你订阅了数据库里的 subjects,只要 subjects 变了,Flow 就通知 UI:“数据更新了,重新显示。”
3. 老师强调的重点
重点 1:GitLab 是 assignment collaborative work 的必需工具 老师一开始就说要先看 ED forum,因为这对 assignment collaborative work 很 critical。她明确说 GitLab is a must to use,并且 faculty 已经给每个 team 配置了 dedicated GitLab repository。marking 会看这个 faculty GitLab repository,而不是你自己私下建的 GitHub/GitLab。
为什么判断重要:
老师在正式技术内容前花时间讲这个,说明它直接影响 assignment marking。她还说 commit history 很难隐藏个人缺少 engagement,因此会被用来看 individual contribution。
main/master branch 是最终版本。
可以开多个 development/working branch。
测试好的功能最终要 merge 到 main/master。
建议每天或一天多次 commit/push。
Git activity history 会影响个人贡献判断。
重点 2:Room 是 A2 / A4 必须实现的 feature 老师在讲本地数据持久化时明确说,Room 是 Assignment 2 和 Assignment 4 的 must implement feature。她还说 Room 不是唯一可以用的数据库,但它是必须用的数据库;你可以额外使用 Firebase Firestore、cloud database、vector database 等,但 Room 仍然 mandated。transcript 里有一处可能把 Room 转写成 Zoom,结合上下文应理解为 Room。
为什么判断重要:
这不是普通知识点,而是 assignment requirement。没有 Room,可能会直接影响实现要求和分数。
重点 3:不要让 UI 直接访问 DAO / Entity 老师说得很强烈:never never allow the outside world directly access your entities;如果 UI 直接访问 DAO 或 data entity,是 very wrong。她解释 Repository 的意义就是防止外部直接碰底层数据。
为什么判断重要:
这是架构原则,也是 assignment 代码检查时容易暴露的问题。如果你的 Composable 里直接调用 DAO,大概率说明架构不对。
你要记住标准链路:
UI / Composable
→ ViewModel
→ Repository
→ DAO
→ Room Database / Entity
重点 4:数据库访问是 slow and unreliable I/O,不能 block UI thread 老师反复说 database I/O 是 slow and unreliable,会 block main UI thread,因此要用 coroutine 管理。Coroutine 课件也明确写了 Rule 1:Do not block main/UI thread;Rule 2:不要从 UI thread 外访问 Android UI toolkit
为什么判断重要:
这是 Room 和 Coroutines 放在同一周讲的原因。你不能只会写 Entity/DAO,还要知道为什么 DAO 和 Repository 的操作要是 suspend、为什么 ViewModel 要 launch(Dispatchers.IO)。
Database access → asynchronous。
Network access → asynchronous。
Large local file access → asynchronous。
不可预测耗时的任务 → asynchronous。
重点 5:ViewModel 是 UI 和 Repository 的 mediator / state holder 老师在课堂上问学生“如果 UI involved,谁是 stakeholder?”答案是 ViewModel。她强调 ViewModel 是 UI 和 Repository 中间的 mediator。Room 课件也把 ViewModel 说成 UI state holder,用来管理 UI-related data,并在 configuration changes 中保留和共享 Room data。
为什么判断重要:
这是 Compose + Room 结合的关键。很多学生会把逻辑写进 Composable,或者搞不清 ViewModel 和 Repository 的区别。
ViewModel 负责 UI state。
Repository 负责 data access abstraction。
ViewModel 里一般不直接写数据库 SQL。
ViewModel 调 Repository,Repository 调 DAO。
重点 6:Flow 是本周非常关键的概念 老师说 Flow 是 very critical concept,并解释它 built upon coroutine。课件也说 Flow 可以 emit multiple values sequentially,Room 支持 Flow return types,当数据库变化时自动 emit 新值,UI 用 collectAsState() 转成 State
为什么判断重要:
Flow 是 Room 数据自动更新 UI 的关键。如果你只理解 suspend function 返回一个值,就不懂为什么 DAO 的 query 返回 Flow<List<Subject>>。
suspend function:通常返回一次结果。
Flow:可以持续发出多个结果。
Room + Flow:数据库变了,UI 可以自动更新。
Compose UI:用 collectAsState() 收集 Flow。
重点 7:companion object / singleton / synchronized / @Volatile 老师花时间解释 INSTANCE 为什么大写、companion object 是 singleton pattern 的 Kotlin 实现、 synchronized(this) 是为了 thread safety、 @Volatile 是为了让 INSTANCE 更新对所有 threads 立即可见。Room 课件第 13 页也专门讲 Companion Object。
为什么判断重要:
这部分看起来像细节,但非常适合出 quiz multiple-choice:它考你是否理解“为什么 Room database 只能创建一个 instance”和“多线程同时访问时怎么保证安全”。
companion object:帮助实现 singleton。
INSTANCE:保存唯一 database instance。
synchronized:同一时间只允许一个 thread 创建 instance。
@Volatile:保证不同 thread 看到最新值。
重点 8:A2/A4 的 AI acknowledgement 和英文要求 老师提醒过去 missing AI acknowledgement 会严重扣分,并说 A4 的 AI acknowledgement 预计要超过 20 页,需要记录 prompt、response、你如何修改/采纳 AI 输出。她还特别回答了中文 AI 对话的问题:未来 conversation/submission 尽量使用 English,或者至少翻译成 English,因为 TA 不一定能读中文,课程是 English-convened course。
为什么判断重要:
这是 assignment marking 和 academic integrity 重点,不是普通课堂闲聊。A4 官方要求中也提到 GitLab link、Gen AI acknowledgement、task allocation form 和 Git commit history 会用于判断个人贡献。
4. transcript 里补充的重要信息 GitLab 具体操作提醒 课件没有讲 GitLab,但老师口头强调:faculty GitLab repository 是 marking 会看的唯一正式 repository;可以有多个 branch,但 main/master 是最终版本;commit history 会用于判断个人贡献;建议 daily commit/push。
A2 提交提醒 老师说官方 due date 是 Friday 晚上,但她口头给了一个实际提醒:如果周五晚来不及,不要熬夜;如果能在 Saturday lunch time 前提交,没有 penalty。只有一个 group member 需要提交,可以多次尝试提交;zip 文件里要包含所有 required documents,包括 AI acknowledgement。这个是口头提醒,具体仍应以 Moodle / ED 最新要求为准。
AI acknowledgement 的严重性 老师提到 A1 中 missing AI acknowledgement 会导致 significant deduction,并提醒未来 A2/A4 不要再犯。A4 甚至需要很详细的 AI history,可能超过 20 页。
英文提交和 AI conversation 有学生问中文 AI 对话可不可以。老师说虽然她能读中文,但 TA 可能不能读;课程是英文授课/英文提交,因此 future conversations and submissions should be English only,或至少翻译成英文。
Lab 7 source code 很重要 老师说这周 applied class / lab notes 里有 Room configuration、KSP configuration 和各个 class/component 的 source code。她建议学生打开 Android Studio 对照代码看,否则概念很难解释。
Room 的 assignment 设计判断 老师补充说 Room 适合本地、小规模、隐私相关数据。你也可以用 cloud database,例如 Firebase Firestore、document database、vector database,但要 justify 哪些数据本地存、哪些数据云端存。Room 仍然必须用。
Entity 命名建议 课件说 tableName 和 ColumnInfo 可以改名;老师口头更明确地建议:assignment 设计更复杂时,最好显式命名 table 和 column,避免 conflict。
KSP 如果没配置会编译失败 老师补充说 Room 的 annotation 依赖 KSP 处理。如果没有配置 KSP,代码会 compile 不过,IDE 会出现红线或报错。
Android Studio / Kotlin 版本兼容问题 老师提醒如果更新到最新 Android Studio / Kotlin / patches 后,lab code 出错,截图并告诉 TA 或发 ED forum,因为依赖版本可能导致兼容问题。这个是课件没有展开的实用提醒。
ViewModel 中不需要把函数本身写成 suspend 老师口头强调:ViewModel 是 UI 和 Repository 之间的 stakeholder,ViewModel 里可以写普通函数,但在里面用 viewModelScope.launch(Dispatchers.IO) 调用 Repository 的 suspend function。很多学生容易混淆这里。
Database Inspector 老师最后演示了 Android Studio 的 App Inspection / Database Inspector:app 必须处于 running mode,然后可以查看本地 Room database、entities/tables 和当前数据。这是检查 Room 是否真的存进去的实用方法。
Week 9 quiz 格式 老师提醒 Week 9 有 in-class quiz,1 小时,16 道题,multiple options / multiple selection,没有 open question,不需要手写代码,但可能需要读代码、理解概念。
课件和 transcript 的小冲突 / 转写误差 transcript 中有些词明显是语音转写错误,例如 DAO 被转成 DIO,Room 被转成 Zoom,SQLite 被转成 SQI Light,Kotlin coroutine 被转成 call routine/core routine。结合课件和上下文,应按 DAO、Room、SQLite、Kotlin coroutines 理解。
另外,课件标准代码写 version = 1, exportSchema = false;老师口头说如果不做 migration 不用太纠结 version/exportSchema。作业中建议优先照课件/lab 标准代码写,避免不必要错误。
5. 这周最可能要掌握的考点 / 作业相关点
最可能和 assignment 有关 能不能在 app 中正确实现 Room 因为老师明确说 Room 是 A2/A4 must implement feature。你至少要会写 Entity、DAO、Database、Repository、ViewModel,并让 UI 能新增、读取、更新、删除数据。
能不能解释为什么用 Room 不是只复制代码,而是要说明:哪些数据适合本地保存,为什么本地保存更合适,哪些数据可以用 cloud database。老师明确说这是 design decision。
GitLab commit history 和 task allocation A4 官方要求中 individual mark 会参考 Git commit history 和 task allocation form;老师口头也强调 commit history 很难伪装个人贡献
AI acknowledgement Assignment 提交必须包含 AI acknowledgement。A4 需要非常详细,包含 prompt、response 和你如何修改/采纳 AI 输出。缺失或编造会严重影响分数
main/master branch 是 final version marker 会看 official faculty GitLab repository 的 main/master branch 和 activity history。不要只在本地或私人 GitHub 里写完而不 merge/push 到 official repo。
最可能和 quiz / exam 有关 哪些任务需要 asynchronous / coroutine Database operations、network access、large local file access、unpredictable running time tasks。老师口头反复举例,下周 Retrofit 也会继续用
suspend fun 的含义 suspend 不是“开一个新线程”的意思,而是允许 coroutine 暂停和恢复,不阻塞当前 thread。这个容易考概念辨析。
Dispatcher 的选择
Room / database / network → Dispatchers.IO
CPU-heavy computation → Dispatchers.Default
UI update → Dispatchers.Main
临时切换 → withContext(...)
这是典型 multiple-choice 考点。
suspend function 通常返回一个值。
Flow 可以连续 emit 多个值。
Room 支持 Flow,当数据库变化时自动发出新数据。
Compose 用 collectAsState() 转成 State。
DAO / Repository / ViewModel 的职责区别 这部分老师讲得很久,还用了类比。很可能通过“哪一层应该调用哪一层”来考
Singleton database companion object、INSTANCE、synchronized、@Volatile 分别做什么。这部分既在课件有专门页,也在课堂口头解释了多线程安全
Migration / fallbackToDestructiveMigration 要知道 destructive migration 可能 drop and recreate tables,导致数据丢失;只有在可以接受丢失数据时才适合
6. 我应该怎么学这周内容
推荐学习顺序 UI / Composable
→ ViewModel
→ Repository
→ DAO
→ Database
→ Entity
Entity:我要存什么?
DAO:我要怎么操作?
Database:数据库怎么创建?
Repository:外部怎么安全访问数据?
理解 ViewModel 为什么在 UI 和 Repository 中间。重点看:
AndroidViewModel(application)
init { cRepository = SubjectRepository(application) }
val allSubjects = cRepository.allSubjects
viewModelScope.launch(Dispatchers.IO) { ... }
重点不是背所有 coroutine API,而是先掌握:
DAO:
fun getAllSubjects(): Flow<List<Subject>>
Repository:
val allSubjects = subjectDao.getAllSubjects()
ViewModel:
val allSubjects = cRepository.allSubjects
Composable:
val subjects by subjectViewModel.allSubjects.collectAsState(initial = emptyList())
必须先搞懂的基础概念 Kotlin data class
annotation,例如 @Entity、 @Dao、 @Database
primary key
interface
suspend function
Flow / List / State 的基本区别
main thread vs worker thread
ViewModel 的作用
Compose 里 state change 会触发 UI 更新
哪些内容属于“理解型” 为什么数据库操作不能 block UI thread。
为什么 UI 不应该直接访问 DAO。
Repository 为什么存在。
ViewModel 为什么是 state holder。
Flow 为什么适合数据库实时更新。
Coroutine 的 suspend/resume 为什么比 callback 更方便。
本地 Room 和远程 cloud database 如何分工。
哪些内容属于“记忆型”
哪些内容属于“应用型” 给自己的 assignment 设计 Entity。
给每个 Entity 写 DAO。
写 Repository wrapper functions。
写 ViewModel 调用 Repository。
用 Dispatchers.IO 跑 insert/update/delete。
用 Flow + collectAsState() 让 UI 自动刷新。
用 Database Inspector 检查数据。
用 GitLab branch/commit/merge 展示个人贡献。
哪些内容只需要了解 KSP 和 kapt 的底层区别。
schema migration 的高级细节。
automated migration vs manual migration。
sensor Flow example 的完整实现。
WorkManager / JobScheduler / Service 的深入用法。
withContext(...) 的复杂场景。
哪些内容需要重点掌握 Room 的完整数据流。
DAO 和 Repository 的区别。
ViewModel 为什么不能让 UI 直接碰数据库。
suspend fun + viewModelScope.launch(Dispatchers.IO) 的组合。
Flow 如何把数据库变化变成 UI state。
Singleton database 的基本原因。
Assignment 中 Room、GitLab、AI acknowledgement 的要求。
最容易混淆的地方 Room vs SQLite SQLite 是底层数据库;Room 是 Android Jetpack 提供的上层包装。
Entity vs table row Entity class 定义表结构;Entity instance 才是表里的一行数据。
DAO vs Repository DAO 直接定义数据库操作;Repository 包装 DAO,对 ViewModel 提供 clean API。
ViewModel vs Repository ViewModel 管 UI state;Repository 管 data access。
suspend function vs coroutine suspend fun 表示这个函数可以被 coroutine 暂停/恢复;真正启动 coroutine 通常用 launch {}。
Flow vs List List<Subject> 是一次性列表; Flow<List<Subject>> 是持续发出列表更新的数据流。
Dispatchers.IO vs Dispatchers.Main 数据库/网络用 IO;更新 UI 用 Main。
Scope vs Dispatcher Scope 管生命周期;Dispatcher 管在哪类线程上跑。
main/master branch vs dev branch dev branch 用来开发;main/master 是 marker 会看的最终版本。
学完后你应该能回答这些问题,才算掌握 为什么 Android app 不能在 main thread 里做 database operation?
Room 和 SQLite 是什么关系?
Entity、DAO、Database、Repository、ViewModel 分别负责什么?
为什么 UI 不应该直接调用 DAO?
@Entity、 @Dao、 @Database 分别标记什么?
@Query 里参数为什么要写 :parameterName?
为什么 DAO 的 insert/update/delete 要写成 suspend fun?
为什么 ViewModel 里用 viewModelScope.launch(Dispatchers.IO)?
Flow<List<Subject>> 比 List<Subject> 多了什么能力?
collectAsState() 在 Compose 里做什么?
companion object、INSTANCE、synchronized、@Volatile 各自作用是什么?
如果 assignment 里同时有 Room 和 Firebase,如何解释各自保存什么数据?
如何用 Database Inspector 检查本地 Room 数据?
GitLab commit history 为什么会影响 individual contribution?
7. 给我一份简短复习清单
Room 架构 checklist
Kotlin / Room code checklist
Coroutines checklist
Assignment checklist
8. 如果我是初学者,你再用更简单的话解释一遍 怎么让 Android app 记住用户输入的数据,而且不要因为保存数据而把界面卡住。
Entity 就是图书馆里“书”的类型。比如每本书有 id、title、author。放到课程例子里,每个 Subject 有 uid 和 name。
DAO 就是你可以对书做的操作:借书、还书、找书、更新书的信息。
Database class 就是创建和管理这个图书馆系统。
Repository 就是服务台。用户不能直接冲进书库拿书,必须通过服务台办理。
ViewModel 就是前台经理,它负责和界面沟通:用户点了按钮,它告诉 Repository 去处理。
UI / Composable 就是用户看到的屏幕,比如新增课程按钮、课程列表、删除图标。
因为数据库操作可能很慢。手机 app 的界面有一个主线程,也叫 UI thread。这个线程要负责按钮点击、文字显示、页面刷新。如果你让它去慢慢查数据库,它就没空响应用户,app 会卡。
所以 Kotlin coroutine 的作用就是:把慢活交给后台工人做。
UI 收到点击。
UI 告诉 ViewModel。
ViewModel 用 viewModelScope.launch(Dispatchers.IO) 开一个后台任务。
后台任务调用 Repository。
Repository 调 DAO。
DAO 把数据写入 Room database。
数据库变了以后,Flow 发出新数据。
Compose 用 collectAsState() 收到新数据,界面自动刷新。
Room 负责把数据存在手机里;Coroutine 负责不要让保存/读取数据卡住界面;Flow 负责数据库变了以后通知 UI;ViewModel 和 Repository 负责让结构不要乱。
Assignment 里,你最重要的是不要只复制代码,而是能解释:
我为什么需要 Room?
我哪些数据存在本地?
我的 Entity 是什么?
我的 DAO 有哪些操作?
我的 UI 有没有通过 ViewModel 和 Repository 访问数据?
我的数据库操作有没有用 coroutine / Dispatchers.IO?
我的数据变化能不能通过 Flow 自动更新界面?
我的 GitLab commit history 能不能证明我真的做了工作?
我的 AI acknowledgement 有没有详细记录?