news 2026/8/23 13:25:14

Connect You 开源联系人应用开发者指南:Jetpack Compose + Room 架构完整解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Connect You 开源联系人应用开发者指南:Jetpack Compose + Room 架构完整解析

Connect You 开源联系人应用开发者指南:Jetpack Compose + Room 架构完整解析

【免费下载链接】ConnectYouPrivacy focused contacts and SMS messenger app built with MD3项目地址: https://gitcode.com/gh_mirrors/co/ConnectYou

Connect You 是一款注重隐私、基于 Material Design 3 的开源 Android 联系人管理 + 短信应用,完整采用 Jetpack Compose 构建 UI、Room 管理本地数据。本文带你从目录结构到 Repository 层双数据源设计,快速看懂这套 MVVM 架构是如何落地的。

项目分层架构一览:先看目录布局

整个应用只有一个模块app,但内部严格按照「数据层 → 领域层 → 表现层」三层组织,位于 app/src/main/java/com/bnyro/contacts/ 下:

目录职责
表现层presentation/Compose 界面、ViewModel、可复用组件
导航层navigation/路由定义与深链处理
领域层domain/数据模型、枚举、Repository 接口
数据层data/Room 数据库与 DAO
工具层util/备份、权限、联系人工具类

这种布局的好处是:界面只依赖 ViewModel,ViewModel 只依赖 Repository 接口,换数据源时界面代码零改动——这正是后文「双数据源」设计的价值所在。

Room 数据库设计:3 张表存下所有联系人数据

核心数据库定义在 AppDatabase.kt,当前版本为 8,并声明了 2→3→4→5 与 6→7→8 的多段 AutoMigration:

@Database( entities = [LocalContact::class, DbDataItem::class, SmsData::class], autoMigrations = [ AutoMigration(2, 3), AutoMigration(3, 4), // ... ], version = 8 ) abstract class AppDatabase : RoomDatabase()

设计上有两个值得学习的点:

  • EAV 模式存属性:联系人主表LocalContact只存姓名、机构、收藏位等固定字段;手机号、邮箱、生日、备注等可变数量的属性统一放进DbDataItem表,用category字段(枚举 DataCategory.kt 中的 NUMBER / EMAIL / EVENT / NOTE…)区分类型。这样新增一种属性类型不需要改表结构。
  • AutoMigration 声明式升级:版本升级只靠注解驱动,数据库的完整演进历史可在 app/schemas/ 目录看到 2 到 8 共 7 个版本的 schema 快照 JSON,方便做数据校验。

Repository 双数据源:本地库 vs 系统联系人

这是全项目最有架构价值的部分。领域层定义了统一接口 ContactsRepository.kt:

interface ContactsRepository { val label: String suspend fun createContact(contact: ContactData) suspend fun getContactList(): List<ContactData> // ... }

两个实现各走一条完全不同的技术路线:

实现存储位置技术要点
LocalContactsRepository.kt应用私有 Room 库头像存文件、属性存 DbDataItem 表
DeviceContactsRepository.kt系统 ContactsContractContentProvider 批量操作 + 权限校验
  • 本地实现:头像不进数据库,而是以联系人 ID 命名写入filesDir/images目录(见saveProfileImage),避免了 Room 中大图片的性能问题。
  • 设备实现:所有写入都通过ContentProviderOperation组装成批量操作再applyBatch,并用@RequiresPermission注解约束READ_CONTACTS/WRITE_CONTACTS权限。
  • 切换逻辑在 ViewModel:ContactsModel.kt 中通过contactsSource状态决定当前注入哪个实现,UI 层对数据从哪来完全无感知。

MVVM + Compose 状态管理:ViewModel 怎么做

表现层每个屏幕对应一个ViewModel(presentation/screens/),以联系人列表的 ContactsModel.kt 为例:

  1. mutableStateOf直接驱动 Compose 重组contactsSource by mutableStateOf(...),用户切换「本地 / 设备」来源时 UI 自动刷新。
  2. UI 状态用密封类建模:列表状态 ContactListState.kt 定义Loading / Success / Error等形态,界面只需when分发,杜绝 null 判断散落各处的经典问题。
  3. 并行加载:初始化时通过async+awaitAll并发拉取两个数据源,配合Dispatchers.IO执行耗时 IO。
  4. 无 Hilt,手工依赖注入:ViewModel 通过viewModelFactory { initializer { ... } }手动构造并传入两个 Repository,保持轻量无注解处理器。

导航与深链:可序列化的路由对象

路由定义在 NavRoutes.kt,所有路由都是@Serializable密封类,参数直接作为类字段:

@Serializable data class MessageThread( val address: String, val body: String? = null ) : NavRoutes()

它还内置了connectyou://message/<号码>这类深链navDeepLink),允许从快捷方式或系统短信意图直接跳转到对应会话——导航配置见 NavContainer.kt。

隐私优先的配套设计

  • 自动备份:BackupWorker.kt 定时导出,VcardHelper.kt 负责 vCard 导入导出,ZipUtils.kt 打包并可选密码加密(PasswordUtils.kt)。
  • 本地短信收件箱:MmsReceiver.kt 捕获短信/MMS 写入 Room 的SmsData表,形成独立于系统短信应用的私有存档。
  • 生物识别:BiometricAuthUtil.kt 为打开加密备份提供指纹/面容解锁。

总结:这套架构最值得抄作业的 3 个点

  1. 接口先行:Repository 接口放在 domain 层,Room 与系统 ContentProvider 两种数据源对上层透明,测试和扩展都容易。
  2. EAV 存属性:用category + value的通用表替代宽表,新增联系人字段类型零 schema 变更。
  3. 密封类建模 UI 状态 + 手动工厂注入:不引入重量级 DI 框架,仅用 Compose State 和 ViewModel 就实现了清晰的单向数据流。

按「先读 ContactsRepository.kt 接口 → 再对比两个实现 → 最后看 ViewModel 如何消费」的顺序走一遍源码,半天时间就能完整理解这个项目的架构脉络,也为你自己的 Android 联系人/数据管理类应用提供了一套可直接参考的模板。

【免费下载链接】ConnectYouPrivacy focused contacts and SMS messenger app built with MD3项目地址: https://gitcode.com/gh_mirrors/co/ConnectYou

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/23 13:25:09

从斯大林排序算法看算法正确性与数据完整性

在实际编程学习和算法讨论中&#xff0c;我们偶尔会遇到一些并非来自计算机科学正统&#xff0c;而是源于网络社区文化或幽默段子的“算法”概念。“斯大林排序算法”就是这样一个典型例子。它并非一种真正用于解决排序问题的有效算法&#xff0c;而更像是一个带有讽刺意味的编…

作者头像 李华
网站建设 2026/8/23 13:22:24

猫抓 Cat-Catch:免费的网页视频资源嗅探与流媒体下载扩展

猫抓 Cat-Catch&#xff1a;免费的网页视频资源嗅探与流媒体下载扩展 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 猫抓&#xff08;cat-catch&a…

作者头像 李华
网站建设 2026/8/23 13:20:55

BBDown 命令行下载器:一条命令把 B 站视频存成本地 MP4

BBDown 命令行下载器&#xff1a;一条命令把 B 站视频存成本地 MP4 【免费下载链接】BBDown Bilibili Downloader. 一个命令行式哔哩哔哩下载器. 项目地址: https://gitcode.com/gh_mirrors/bb/BBDown 收藏夹里的课程视频突然 404 了&#xff0c;你才想起该备份。BBDown…

作者头像 李华
网站建设 2026/8/23 13:18:37

多元分数多项式为何衰落?从统计建模稳定性与机器学习范式演变谈起

1. 从“万能钥匙”到“工具箱里的冷门工具”&#xff1a;多元分数多项式的兴衰启示 在统计建模和机器学习的世界里&#xff0c;我们总在寻找一种“万能钥匙”——一种既能捕捉复杂非线性关系&#xff0c;又易于解释、计算高效且稳健的方法。大约在二十多年前&#xff0c;一种名…

作者头像 李华