SimpMusic 现代 Android 架构指南:Clean Architecture 分层、依赖注入与多模块化实战
音视频【免费下载链接】SimpMusicA cross-platform music app using YouTube Music for backend项目地址https://gitcode.com/gh_mirrors/si/SimpMusic点击查看免费下载导读本文以仓库内 AI 开发规范文档.claude/skills/android-architecture/SKILL.md为核心骨架系统讲解现代 Android及 Compose Multiplatform应用的 Clean Architecture 三层架构、Hilt/依赖注入规范与多模块化策略并对照 SimpMusic 仓库的真实代码给出可落地的验证证据。读完你将掌握如何划分 UI / Domain / Data 三层的职责与依赖方向、如何用注解与模块组织依赖注入、如何设计:core:*与:feature:*的多模块工程结构以及如何在 SimpMusic 这种 Compose Multiplatform 项目中落地同一套原则。一、High-Level Layers三层架构与依赖方向SKILL 文档给出的第一条铁律是将应用拆分为三个主层依赖必须严格向内向下流动到核心逻辑绝不允许反向依赖。1. UI Layer表现层职责展示数据、处理用户交互。组成Activity、Fragment、Composable、ViewModel。依赖只依赖 Domain 层简单项目也可直接依赖 Data 层接口绝不能直接依赖 Data 层的实现细节。在 SimpMusic 中表现层集中在composeApp的 commonMain 与androidAppAndroid 入口 MainActivity.kt 负责组装 Koin 模块、绑定媒体服务、最终以setContent { App(viewModel) }挂载 Compose 界面共享 UI 根组件 App.kt 只收集SharedViewModel暴露的StateFlow如sleepTimerState、nowPlayingState、themeMode通过collectAsStateWithLifecycle()订阅——这正是UI 层只面向 ViewModel不触碰数据实现的体现全部 ViewModel 位于composeApp/src/commonMain/kotlin/com/maxrave/simpmusic/viewModel/它们统一继承自 BaseViewModel.kt。2. Domain Layer业务逻辑层【可选但推荐】职责封装复杂业务规则、促进复用。组成Use Case如GetLatestNewsUseCase、Domain Model纯 Kotlin data class。纯 Kotlin不得包含任何 Android 框架依赖不能出现android.*import。依赖只依赖 Repository 接口。SKILL 特别强调 Domain 层的纯 Kotlin属性。SimpMusic 对此的执行非常彻底settings.gradle.kts将:common、:data、:domain三个核心模块显式映射到仓库根目录下的coregit 子模块project(:domain).projectDir File(coreDir, domain)而core/domain从 CLAUDE.md 的架构说明看承载的是领域模型、用例、Repository 接口、业务规则是纯 Kotlin 逻辑层不依赖任何 Android 框架。3. Data Layer数据层职责管理应用数据拉取、缓存、保存。组成Repository 实现、Data SourceRetrofit API、Room DAO。依赖只依赖外部数据源与第三方库。对应到 SimpMusiccore/data提供 Repository 实现与 Room 数据库core/service/*提供网络服务实现。仓库中AlbumViewModel依赖的是com.maxrave.domain.repository.AlbumRepository接口而具体的 Room/网络实现被屏蔽在 Domain 层之后——UI 层永远看不到 SQLite 与网络细节。二、Dependency InjectionHilt 规范与 SimpMusic 的 Koin 等价实现SKILL 规定使用 Hilt 完成所有依赖注入并给出了四个注解用法。但必须指出一个仓库实测事实当前 SimpMusic 工程中不存在任何 dagger/hilt 依赖全仓库检索零命中实际选用的是 Koin。两者的角色等价——都是把谁依赖谁从手工new中解放出来。下面先完整保留 SKILL 的 Hilt 规范再逐条给出仓库中的 Koin 对应物。SKILL 中的 Hilt 用法规范原文HiltAndroidApp标注Application类。AndroidEntryPoint标注 Activity 与 Fragment。HiltViewModel标注 ViewModel并使用标准的构造函数注入。ModulesModuleInstallIn(SingletonComponent::class)用于应用级单例如 Network、Database。抽象类中使用Binds绑定接口实现比Provides更干净。SimpMusic 中的 Koin 等价实现HiltSKILL 规范SimpMusicKoin 实现HiltAndroidAppApplicationSimpMusicApplication.kt 继承KoinComponent在onCreate()里startKoin { androidContext(...); loadAllModules(...); loadKoinModules(viewModelModule) }AndroidEntryPointActivityMainActivity.kt 通过by injectSharedViewModel()注入并在onCreate/onDestroy中loadKoinModules/unloadKoinModules(viewModelModule)以重建 ViewModelHiltViewModel构造函数注入ViewModelModule.kt 中viewModel { AlbumViewModel(get(), get()) }声明全部 ViewModel 及其构造依赖Module单例loadAllModules(AppIdentity(...))从core/data的 Koin 模块加载网络、数据库等单例Koin 在commonMain同样可用App.kt 中SharedViewModel: SharedViewModel koinInject()这是它能在 Compose Multiplatform 的共享代码中取代 Hilt 的关键优势——Hilt 依赖 Android Gradle 插件无法直接服务 jvmMain/iosMain。值得一提的设计细节SKILL 推荐用Binds绑接口实现比Provides更干净。Koin 侧 SimpMusic 也贯彻了面向接口思想——例如ViewModelModule.kt中LoginSyncHostViewModel(get())/LoginSyncSenderViewModel(get())的注释写明Koin resolves dependencies when a ViewModel is created各平台分别绑定自己的 Repository 实现UI 层只依赖 Domain 的 Repository 接口。三、Modularization Strategy多模块工程结构SKILL 建议生产级应用采用多模块策略以提升构建速度与关注点分离并给出标准模块划分:app主入口连接各 feature:core:model共享领域模型纯 Kotlin:core:dataRepository、DataSource、Database、Network:core:domainUse Case 与 Repository 接口:core:ui共享 Composable、主题、资源:feature:[name]独立 feature 模块自带 UI 与 ViewModel只依赖:core:domain与:core:ui。SimpMusic 的实际模块拓扑对照 settings.gradle.kts仓库的模块命名做了自己的取舍但分层思想与 SKILL 完全一致主入口:androidAppAndroid 壳、:vivoAndroidAppvivo 定制壳、:composeApp共享 UI 业务可运行 Desktop、:desktopApp核心三模块:common、:domain、:data——全部通过project(...).projectDir File(coreDir, ...)指向core子模块服务模块对应 SKILL 的 Data Source:ktorExt、:kotlinYtmusicScraper、:spotify、:aiService、:lyricsService、:listenTogether、:loginSync等映射到core/service/*媒体模块:media3、:media3-uiAndroid 播放、:media-jvm、:media-jvm-ui桌面播放映射到core/media/*功能开关型成对模块:crashlytics/:crashlytics-empty、:cast/:cast-empty、:lastfm/:lastfm-empty——Full 版与 FOSS 版通过isFullBuild属性在构建期二选一保证 F-Droid 构建不含任何闭源依赖。可以看到 SimpMusic 并没有生搬硬套:core:model、:core:ui、:feature:[name]的命名而是按共享代码放在composeApp 多平台 commonMain、平台专属能力拆成 expect/actual 或独立模块的思路组织——这是 Compose Multiplatform 对 SKILL 模块化原则的合理演绎。依赖方向也严格执行高层只能依赖低层CLAUDE.md 给出的依赖链为UI(composeApp) → Domain(core/domain) → Data(core/data) → Service(core/service/*) → Common(core/common)与 SKILL 的依赖向内流动一致。例如core/service/loginSync的说明明确写道服务层只负责传输、不携带业务语义Domain 层持有LoginSyncHostRepository/LoginSyncSenderRepository接口Data 层才是唯一知道 payload 含义的地方——这正是三层边界在真实工程中的贯彻。四、Checklist落地实现自检清单SKILL 提供了三条实施检查项结合仓库代码逐条验证确保 Domain 层无 Android 依赖从源码结构看core/domain被独立映射到core子模块且不引入android.*composeApp的 commonMain 虽然包含 UI 与 ViewModel但 ViewModel 只 importandroidx.lifecycle.ViewModel如 BaseViewModel.kt领域模型与业务规则全部经由com.maxrave.domain.*引用边界清晰。Repository 默认提供主线程安全的 suspend 函数内部按需使用Dispatchers.IOAlbumViewModel.kt 中albumRepository.getAlbumData(browseId)、albumRepository.getAlbumAsFlow(browseId)均为挂起函数或 FlowUI 侧统一在viewModelScope.launch中订阅没有在主线程直接执行 I/O 的写法。ViewModel 通过StateFlow与 UI 层交互这是 SimpMusic 最显著的统一模式。以 AlbumViewModel.kt 为例private val _uiState: MutableStateFlowAlbumUIState MutableStateFlow(AlbumUIState.initial()) val uiState: StateFlowAlbumUIState _uiState再配合_uiState.update { it.copy(...) }线程安全地更新状态UI 侧用collectAsStateWithLifecycle()收集。此模式在仓库中被 Systematically 使用AnalyticsViewModel、ArtistViewModel、AutoEqViewModel等同构与配套规范.claude/skills/android-viewmodel/SKILL.md中StateFlow 必须有初始值、对外只暴露只读 StateFlow、用.update {}更新的建议完全一致。五、在 Compose Multiplatform 中执行架构原则的补充要点SKILL 面向传统 Android 工程编写SimpMusic 则把它平移到了 KMP 共享代码上有三点值得注意ViewModel 不再需要AndroidEntryPointcommonMain 的 ViewModel 通过BaseViewModel : ViewModel(), KoinComponent直接使用by inject...()如mediaPlayerHandler、SongRepository绕开了 Activity/ViewModelStore 的 Hilt 桥接天然跨 Android/Desktop 复用。纯 Kotlin 边界要延伸到服务层由于:data以implementation依赖服务模块UI 无法直接看到服务层如lyricsService的说明the dependency stops there andcomposeAppcannot see it——the layering rule working as intended。UI 需要的数据一律经 Domain 的 Repository 接口中转这是三层原则在依赖图上最直观的体现。成对空实现模块是平台/发行版边界的另一种表现cast-empty、crashlytics-empty、lastfm-empty都以同名公开 API 返回 false/no-op 的桩实现隔离闭源 SDK功能代码与发行策略解耦属于多模块化的高级用法。参考资料仓库内规范原文.claude/skills/android-architecture/SKILL.md配套 ViewModel 规范.claude/skills/android-viewmodel/SKILL.md模块清单与子模块映射settings.gradle.kts依赖版本目录gradle/libs.versions.toml依赖注入装配ViewModelModule.kt、SimpMusicApplication.ktViewModel 基类与 StateFlow 示例BaseViewModel.kt、AlbumViewModel.kt架构总览CLAUDE.md赞分享音视频【免费下载链接】SimpMusicA cross-platform music app using YouTube Music for backend项目地址https://gitcode.com/gh_mirrors/si/SimpMusic点击查看免费下载相关推荐Koin Android 库绑定模式实战Retrofit、Room、WorkManager 与 Clean Architecture 的依赖注入方案Koin Android 库绑定模式实战Retrofit、Room、WorkManager 与 Clean Architecture 的依赖注入方案 导读 本后端如何用pyLast实现Last.fm用户认证两种授权方式完整对比如何用pyLast实现Last.fm用户认证两种授权方式完整对比 pyLast是一个功能强大的Python库提供了与Last.fm和Libre.fm音乐平台后端LivePortrait技术深度解析高效肖像动画生成与拼接重定向控制LivePortrait技术深度解析高效肖像动画生成与拼接重定向控制 LivePortrait是由快手科技开发的实时肖像动画解决方案通过创新的拼接与重定向控人工智能计算机视觉媒体生成数字人上一篇终极指南Air与Docker完美集成实现Go开发热重载下一篇如何3分钟上手DSH Desktop从下载macOS安装包到第一次官方DSH会话创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

集团顶层设计不是画图:从战略澄清到落地作战地图的实战方法

集团顶层设计不是画图:从战略澄清到落地作战地图的实战方法

很多集团把顶层设计当成一个“写文档”的活,我见过最夸张的一次,项目组交了三百多页报告,封面烫金、装帧精美,可公司内部能讲清里面逻辑的人不超过三个。半年后回访,那本蓝图躺在书架最高层,连塑料封膜都没…

2026/10/14 6:21:26 阅读更多 →
微信小程序开发第一周:从零搭建最小页面到交互实战

微信小程序开发第一周:从零搭建最小页面到交互实战

第一周接触微信小程序开发,最常见的状态是:资料收藏了一堆,视频看了三集,代码一行没写。我自己带新人时就发现,week1 这个阶段最不该贪多,因为小程序虽然看起来只是网页开发的变体,但它的环境、…

2026/10/14 6:21:26 阅读更多 →
结算系统资金安全防护:幂等、对账与资损追回实践

结算系统资金安全防护:幂等、对账与资损追回实践

作为一名长期跟结算系统打交道的人,我对“资损”这两个字有着本能的敬畏。很多人觉得结算就是“算算账”:今天收了多少钱,该付出去多少,两边对得上不就行了。但真正做过这行的人都知道,结算根本不是简单的加减法&#…

2026/10/14 6:21:26 阅读更多 →

最新新闻

麦语言函数手册实战:从零构建可复现的量化指标脚本

麦语言函数手册实战:从零构建可复现的量化指标脚本

简介:麦语言函数手册是文华财经推出的程序化函数库参考文档,面向使用文华平台进行量化策略开发的交易者与编程初学者,帮助其快速查阅函数用法、理解模型编写逻辑。手册系统梳理了自编策略模型支持的各类函数,涵盖历史数据引用&…

2026/10/14 6:57:33 阅读更多 →
高专院校机器视觉课程实践方案:从OpenCV到工业检测项目的落地指南

高专院校机器视觉课程实践方案:从OpenCV到工业检测项目的落地指南

第一次把这门课带上实训台的时候,说实话我心里也没底。机器视觉课程在本科院校都算硬骨头,在高专院校更是容易走样:讲理论学生听不懂,讲算法代码跟不上,买工业相机又怕吃灰。带着这些问题,我前后在几个年级…

2026/10/14 6:57:32 阅读更多 →
三菱PLC通讯协议那么多,到底该用哪个?

三菱PLC通讯协议那么多,到底该用哪个?

三菱 PLC 覆盖串口、以太网、现场总线、工业以太网四大类,特点是自有协议强(CCLink/MC/SLMP)、Modbus 全系标配、高端加 EtherCAT/OPC UA;和汇川相比,CCLink 生态更成熟,EtherCAT 起步稍晚。一、串口协议&a…

2026/10/14 6:57:32 阅读更多 →
纯视觉方案能否取代激光雷达?从BEV到占用网络的技术拆解

纯视觉方案能否取代激光雷达?从BEV到占用网络的技术拆解

最近圈内聊“纯视觉”聊得很凶,正好赶上某新势力品牌旗舰车型X-01交付,全车没有一颗激光雷达,只靠摄像头加神经网络就把城市领航辅助跑了起来,官方甚至直接把“纯视觉”三个字写进了宣传语。我自己的感知算法相关工作做了六七年&a…

2026/10/14 6:57:32 阅读更多 →
AnyPS5实战指南:从局域网串流到远程游玩的全场景方案

AnyPS5实战指南:从局域网串流到远程游玩的全场景方案

1. 项目概述:AnyPS5到底在解决什么问题先聊聊这个项目名。AnyPS5,字面拆开就是"Any"加"PS5"——任何一台PS5、任何一块屏幕、任何一张沙发、任何一段碎片时间,都能把它变成你的游戏现场。我最初接触到这个项目概念时&…

2026/10/14 6:57:32 阅读更多 →
Spring AI Alibaba停更后Java AI工程化重构指南

Spring AI Alibaba停更后Java AI工程化重构指南

1. 项目概述:当一个热门生态组件突然“静音”,Java开发者该盯住什么?“Spring AI Alibaba已停更了,Java还有希望吗?”——这句话最近在几个主流技术社区的讨论区反复刷屏,不是因为某个重大漏洞,…

2026/10/14 6:56:32 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →