Android现代开发推荐 | Android Showcase 2.0

Android现代开发推荐 | Android Showcase 2.0

Android Showcase是一个完整的Android应用程序示例,它使用了现代的Android应用程序开发方法,集成了流行的开发工具、库和代码检查工具,以及强大的测试框架和持续集成(CI)设置。该项目的主要重点是推广模块化、可扩展、可维护和可测试的架构,并结合了最佳的软件开发实践。即使这个应用程序看起来很简单,它包含了所有关键组件,为强大的大规模应用程序打下了基础。

该项目中采用的设计原则和架构选择非常适合更大的团队和更长的应用程序生命周期。这个应用程序不仅展示了功能,而且证明了良好结构化和编写的代码如何作为可扩展和可维护软件开发项目的稳定支柱。无论是新手还是有经验的开发者,都可以从这个项目中学到很多东西。

应用简介

Android Showcase是一个展示各种音乐专辑信息的简单应用程序,它通过使用Last.fm音乐平台API动态获取数据。该应用程序包含多个特性模块,其中包括以下屏幕:

  • 专辑列表屏幕(Album list screen):显示专辑列表
  • 专辑详细信息屏幕(Album detail screen):显示所选专辑的信息
  • 个人资料屏幕(Profile screen):目前是空白(WiP)
  • 收藏夹屏幕(Favourites screen):目前是空白(WiP)

这些屏幕旨在展示应用程序设计和架构的不同方面,以及如何将它们整合到一个完整的Android应用程序中。无论您是初学者还是有经验的开发者,都可以从这个应用程序中学到很多东西。

技术栈

该项目利用 Android 生态系统中的最佳实践和许多流行的库和工具。除非有很好的理由使用非稳定的依赖项,否则大多数库都是稳定版本。

  • 技术栈
    • 100% Kotlin
      • 协程 - 执行后台操作
      • Kotlin Flow - 跨越所有应用层的数据流,包括视图。
      • Kotlin 符号处理 - 启用编译器插件
      • Kotlin 序列化 - 解析 JSON
    • Retrofit - 网络通信
    • Jetpack
      • Compose - 现代、本地 UI 工具包
      • Navigation - 应用内导航
      • Lifecycle - 在生命周期状态更改时执行操作
      • ViewModel - 以生命周期感知的方式存储和管理与 UI 相关的数据
      • Room - 存储离线缓存
    • Koin - 依赖注入(依赖检索)
    • Coil - 图片加载库
    • Lottie - 动画库
  • 现代架构
    • Clean Architecture
    • 使用 Navigation 组件 的单一活动架构
    • MVVM + MVI(表示层)
    • Android 架构组件
      (ViewModel
      , Kotlin Flow
      , Navigation)
    • Android KTX - Jetpack Kotlin 扩展
  • UI
    • 响应式 UI
    • Jetpack Compose - 现代、本地 UI 工具包(用于 Fragment)
    • View Binding - 检索 XML 视图 ID
      (仅用于 NavHostActivity)
    • Material Design 3 - 应用设计系统,提供 UI 组件
    • 主题选择
      • 深色主题 - 应用程序的深色主题(Android 10+)
      • 动态主题 - 使用生成的基于壁纸的主题(Android 12+)
  • CI
    • GitHub Actions
    • 自动 PR 验证,包括测试、linter 和第三方在线工具
  • 测试
    • 单元测试(通过 android-junit5 使用 JUnit 5)- 测试单个类
    • Konsist - 测试代码约定和架构规则
    • UI 测试(Espresso)-
      测试用户界面(WiP)
    • Mockk - 模拟框架
    • Kluent - 断言框架
  • 静态分析工具(linter)
    • Ktlint - 验证代码格式
    • Detekt - 验证代码复杂度和代码气味
    • Android Lint - 验证 Android 平台使用情况
  • Gradle
    • Gradle Kotlin DSL - 定义构建脚本
    • 自定义任务
    • Gradle 插件
      • Android Gradle - 标准 Android 插件
      • Test Logger - 格式化测试日志
      • SafeArgs - 在导航目的地之间传递数据
      • Android-junit5 - 使用 JUnit 5 与 Android
    • 版本目录 - 定义依赖关系
    • 类型安全访问器
  • GitHub 引导
    • Renovate - 自动更新依赖项
    • Stale - 自动关闭陈旧的问题和拉取请求,这些问题和拉取请求在项目中容易积累
  • 其他工具
    • Charles Proxy - 在 debug 构建中启用网络流量嗅探。

模块化架构

我们使用模块化的方式来减少大型系统的复杂性。每个模块是一个独立的构建块,具有明确的目标。我们将每个特性看作是可重用的组件,类似于microservice或私有库。

采用模块化的代码库方法有以下好处:

  • 可重用性 - 可以共享代码并从相同的基础构建多个应用程序。应用程序应该是其特性的总和,其中特性被组织为单独的模块。
  • 关注点分离 - 每个模块都有明确的API。与特性相关的类位于不同的模块中,并且没有显式的模块依赖项不能引用它们。我们严格控制着哪些内容对代码库的其他部分公开。
  • 特性可以并行开发,例如由不同的团队
  • 每个特性可以独立于其他特性进行开发
  • 构建时间更快

模块类型和模块依赖关系

下面的图表展示了项目模块(Gradle 子项目)之间的依赖关系。

应用程序有三种类型的模块:

  • app 模块 - 这是主模块。它包含将多个模块连接在一起的代码(类、依赖注入设置、NavHostActivity等)和基本应用程序配置(Retrofit 配置、所需权限设置、自定义 Application 类等)。
  • feature_x 模块 - 最常见的模块类型,包含与给定特性相关的所有代码。可以在 feature 模块之间共享一些资源或代码(当前应用程序没有此类模块)。
  • feature_base 模块 - 特性模块依赖于它们以共享公共代码。

特性模块结构

我们采用 Clean Architecture 在模块级别实现 - 每个模块都包含自己一组 Clean Architecture 层:

注意,app 模块和 library_x 模块的结构与特性模块的结构稍有不同。

每个特性模块包含非层组件和3个具有不同责任集的层。

表示层

该层最接近用户在屏幕上看到的内容。

presentation 层结合了 MVVMMVI 模式:

  • MVVM - 使用 Jetpack 的 ViewModel 封装一个 common UI state。它通过可观察的状态持有者(Kotlin Flow)公开状态。
  • MVI - action 修改 common UI state 并通过 Kotlin Flow 向视图发出新的状态。

common state 是每个视图的单一真理来源。这种解决方案源于 单向数据流 和 Redux 原则。

这种方法有助于创建一致的状态。状态通过 collectAsUiStateWithLifecycle 方法收集。Flow 集合以受生命周期管理的方式进行,因此不会浪费资源。

状态使用 Immutable 注解标记,Jetpack Compose 使用该注解启用组合优化。

组件:

  • 视图(Fragment) - 观察通用视图状态(通过 Kotlin Flow)。Compose 将由 Kotlin Flow 发出的状态转换为应用程序 UI。将用户交互传递给 ViewModel。视图很难进行测试,因此应尽可能简单。
  • ViewModel - 向视图发出(通过 Kotlin Flow)视图状态的更改,并处理用户交互(这些视图模型不仅仅是POJO 类)。
  • ViewState - 单个视图的通用状态
  • StateTimeTravelDebugger - 记录操作和视图状态转换以便进行调试。
  • NavManager - 单例,用于在 NavHostActivity 内处理所有导航事件(而不是在每个视图内单独处理)。
领域层

这是应用程序的核心层。请注意,domain 层独立于其他任何层。这样可以使领域模型和业务逻辑独立于其他层。换句话说,对其他层的更改(例如更改数据库(data 层)或屏幕 UI(presentation 层))理想情况下不会影响 domain 层的任何代码更改。

组件:

  • UseCase - 包含业务逻辑
  • DomainModel - 定义应用程序中将使用的数据的核心结构。这是应用程序数据的真理来源。
  • Repository 接口 - 保持 domain 层独立于 data layer(依赖反转)。
数据层

包装应用程序数据。为 domain 层提供数据,例如从互联网检索数据并在设备离线时将数据缓存到磁盘缓存中。

组件:

  • Repository 将数据公开给 domain 层。根据应用程序结构和外部 API 的质量,存储库还可以合并、过滤和转换数据。这些操作旨在为 domain 层创建高质量的数据源。存储库(一个或多个)负责从 Data Source 中读取并构建领域模型,并接受要写入 Data Source 的领域模型。
  • Mapper - 将 data model 映射到 domain model(使 domain 层独立于 data 层)。

该应用程序有两个 Data Sources - Retrofit(用于网络访问)和 Room(用于访问设备持久存储的本地存储)。这些数据源可以被视为一个隐式子层。每个数据源由多个类组成:

  • Retrofit Service - 定义一组 API 端点
  • Retrofit Response Model - 定义给定端点的网络对象(数据的顶层模型包含 ApiModels
  • Retrofit Api Data Model - 定义网络对象(响应模型的子对象)
  • Room Database - 持久性数据库,用于存储应用程序数据
  • Room DAO - 与存储的数据进行交互
  • Room Entity - 存储对象的定义

Retrofit API Data ModelsRoom Entities 都包含注解,因此给定的框架了解如何解析数据为对象。

数据流

下图展示了当用户与“专辑列表界面”交互时的应用程序数据流:

依赖管理

使用 Gradle 版本目录 作为集中化的依赖管理,共享第三方依赖项坐标(分组、构件、版本)跨所有模块(Gradle 项目和子项目)。

所有依赖项都存储在 settings.gradle.kts 文件中(默认位置)。Gradle 版本目录包括几个主要部分:

  • [versions] - 声明可被所有依赖项引用的版本
  • [libraries] - 声明库坐标的别名
  • [bundles] - 声明依赖捆绑包(组)
  • [plugins] - 声明 Gradle 插件依赖项

每个特性模块都依赖于 feature_base 模块,因此依赖项在不需要在每个特性模块中显式添加的情况下共享。

该项目启用了 TYPESAFE_PROJECT_ACCESSORS 实验性 Gradle 功能,以生成类型安全的访问器,以引用其他项目。

// Before
implementation(project(":feature_album"))// After
implementation(projects.featureAlbum)

灵感

以下是一些额外的资源。

快速参考表

  • Material Theme Builder - 生成动态材料主题并查看其实际效果
  • Compose Material 3 Components
    - 包含材料组件的列表
  • Core App Quality Checklist - 学习如何构建高质量应用程序
  • Android Ecosystem Cheat Sheet - 包含 200+ 最重要的工具的板
  • Kotlin Coroutines - Use Cases on Android -
    最流行的协程用途

Android 项目

其他高质量的项目将帮助您找到适用于您的项目的解决方案(随机顺序):

  • Compose Samples - 存储库包含一组个别的 Android Studio
  • Jetpack Compose Playground - 这是一个 Jetpack Compose 示例
    项目
  • Now Android - 完全使用 Kotlin 和 Jetpack Compose 构建的功能齐全的 Android 应用程序
  • WhatsApp Clone Compose - 使用 Jetpack Compose 和 Stream Chat SDK
    构建的 WhatsApp 克隆应用程序,用于帮助您了解 Android 中的 Compose
  • Iosched - Google IO 2019 和 2021 的官方 Android 应用程序
  • Android Architecture Blueprints v2 - 展示了各种 Android
    架构方法来开发 Android 应用程序
  • Github Browser Sample - 多个小项目,演示了 Android
    架构组件的使用
  • Clean Architecture Boilerplate - 用于 Android 的清晰
    架构
  • Roxie - common state 方法的坚实示例以及非常好的文档
  • Kotlin Android Template - 模板,可让您在几秒钟内创建预配置的 Android Kotlin 项目

项目地址

https://github.com/igorwojda/android-showcase

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/242073.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Vue】Vue 路由的配置及使用

目录捏 前言一、路由是什么?1.前端路由2.后端路由 二、路由配置1.安装路由2.配置路由 三、路由使用1.route 与 router2. 声明式导航3. 指定组件的呈现位置 四、嵌套路由(多级路由)五、路由重定向1.什么是路由重定向?2.设置 redire…

CSS 设置背景图片

文章目录 设置背景颜色设置背景图片背景图片偏移量计算原点背景图片尺寸设置背景图片位置设置背景图片重复方式设置背景范围设置背景图片是否跟随元素移动测试背景图片 本文概念部分参考:CSS背景background设置 设置背景颜色 background-color 设置背景颜色 设置…

算法训练 day24 | 77. 组合

77. 组合 题目链接:组合 视频讲解:带你学透回溯算法-组合问题 回溯其实和递归是密不可分的,解决回溯问题标准解法也是根据三部曲来进行的。 1、递归函数的返回值和参数 对于本题,我们需要用一个数组保存单个满足条件的组合,还需要另一个结果数…

安全帽识别-赋能深圳自贸中心智慧工地

在当今的建筑行业中,安全管理一直是一个至关重要的议题。深圳自贸中心项目在这方面进行了一次有益的尝试——实施智慧工地安全帽识别系统。本文将对这一创新举措进行简要介绍。 项目背景 深圳自贸中心,作为一项标志性建设项目,承载着城市发展…

acwing讲解篇之93. 递归实现组合型枚举

文章目录 题目描述题解思路题解代码 题目描述 题解思路 本题相当于二叉树的深度优先遍历,树的第i层表示第i个数选或不选,当选择了m次左节点后退出 我们记录当前递归的深度deep 然后用state进行状态压缩,state第i位是1表示选第i个数&#xff…

Linux中测试内存卡的读写速度方法

Linux下有很多工具可以测试内存卡的读写速度。以下是几个常用的工具: dd命令:dd命令可以用来复制文件和设备。通过指定数据块大小,可以测试内存卡的读写速度。例如,可以使用以下命令测试内存卡的写速度: dd if/dev/zer…

浪花 - 搜索标签前后端联调

前传:浪花 - 根据标签搜索用户-CSDN博客 目录 一、完善后端搜索标签接口 二、前后端搜索标签接口的对接 1. 使用 Axios 发送请求 2. 解决跨域问题 3. Axios 请求传参序列化 4. 接收后端响应数据 5. 处理后端响应数据格式 6. 搜索结果为空的页面展示 附&am…

第十一站:多态练习ODU

实现动态切换 ODU.h #pragma once #include <iostream> using namespace std; #define ODU_TYPE_311_FLAG "311" #define ODU_TYPE_335_FLAG "335" enum class ODU_TYPE {ODU_TYPE_311,ODU_TYPE_335,ODU_TYPE_UNKNOW };class ODU{ public:ODU();//发…

linux sudo指令提权

sudo指令 sudo 是在linux中用于以超级用户&#xff08;root&#xff09;权限执行命令的命令。它允许普通用户在执行特定命令时提升其权限&#xff0c;以完成需要超级用户权限的任务。sudo 的名称是 "superuser do" 的缩写。 格式 接受权限的用户登陆的主机 &#xff…

[AI]文心一言出圈的同时,NLP处理下的ChatGPT-4.5最新资讯

前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff1a;https://www.captainbed.cn/z ChatGPT体验地址 文章目录 前言4.5key价格泄漏ChatGPT4.0使用地址ChatGPT正确打开方式最新功能语音助手存档…

C#,入门教程(21)——命名空间(namespace)与程序结构的基础知识

上一篇&#xff1a; C#&#xff0c;入门教程(20)——列表&#xff08;List&#xff09;的基础知识https://blog.csdn.net/beijinghorn/article/details/124094382 编写软件&#xff08;大软件称为系统&#xff09;与盖大楼一个道理。 假设咱们现在需要盖一座名为“天梯大厦”的…

elementUI+el-upload 上传、下载、删除文件以及文件展示列表自定义为表格展示

Upload 上传组件的使用 官方文档链接使用el-upload组件上传文件 具体参数说明&#xff0c;如何实现上传、下载、删除等功能获取文件列表进行file-list格式匹配代码 文件展示列表自定义为表格展示 使用的具体参数说明文件大小展示问题&#xff08;KB/MB&#xff09;文件下载代码…

RDMA Scatter Gather List详解

1. 前言 在使用RDMA操作之前&#xff0c;我们需要了解一些RDMA API中的一些需要的值。其中在ibv_send_wr我们需要一个sg_list的数组&#xff0c;sg_list是用来存放ibv_sge元素&#xff0c;那么什么是SGL以及什么是sge呢&#xff1f;对于一个使用RDMA进行开发的程序员来说&#…

全开源多城市同城信息小程序源码(Laravel 框架),同城分类信息发布便民小程序系统【非DZ】

同城生活分类信息小程序&#xff0c;人才招聘、房产二手 多城市地区同城分类信息发布&#xff0c;商家入驻等功能 小程序前后端代码开源无加密&#xff0c;可进行二次开发 【源码运行要求】 1、需要已认证的微信小程序 2、已备案的域名及服务器空间 推荐使用宝塔面板LinuxPHP…

全球 TOP 20 免费恢复删除的文件/照片的数据恢复软件

如今几乎一切都是数字化的。大多数人选择以数字方式存储所有重要文件、图片和其他数据&#xff0c;因为纯粹是为了方便。虽然数字存储使存储大量数据变得很方便&#xff0c;但它也面临着自己的挑战。 意外删除文件就像将它们存储在硬盘、SD 卡或 USB 驱动器上一样简单。这就是…

带你学C语言-指针(4)

目录 ​编辑 ⚾0.前言 &#x1f3c0;1.回调函数 ⚽2.qsort &#x1f3c9;2.1 qsort函数的模拟实现 &#x1f3be;3.sizeof与strlen对比 &#x1f3be;4.结束语 ⚾0.前言 言C之言&#xff0c;聊C之识&#xff0c;以C会友&#xff0c;共向远方。各位CSDN的各位你们好啊&…

7. UE5 RPG修改GAS的Attribute的值

前面几节文章介绍了如何在角色身上添加AbilitySystemComponent和AttributeSet。并且还实现了给AttributeSet添加自定义属性。接下来&#xff0c;实现一下如何去修改角色身上的Attribute的值。 实现拾取药瓶回血功能 首先创建一个继承于Actor的c类&#xff0c;actor是可以放置到…

python-基础篇-高级变量类型

文章目录 高级变量类型目标知识点回顾 01. 列表1.1 列表的定义1.2 列表常用操作del 关键字&#xff08;科普&#xff09;关键字、函数和方法&#xff08;科普&#xff09; 1.3 循环遍历1.4 **应用场景** 02. 元组2.1 元组的定义创建空元组元组中 **只包含一个元素** 时&#xf…

如何在 Element Plus 中使用自定义 icon 组件 (非组件库内置icon)

先说原理就是将 svg 文件以 vue 组件文件的方式使用 需求&#xff1a;我想要在 Element Plus 得评分组件中使用自定义得图标。 el-rate v-model"value1" /> 组件本身是支持自定义图标的&#xff0c;但是教程中只说明了如何使用 element-plus/icons-vue 图标库内置…

日志记录logging

文章目录 1. logging基础使用1.1 日志的6个级别1.2 logging.basicConfig1.3 案例 2. logging的高级应用2.1 记录器Logger2.2 处理器- Handler2.3 格式器- Formatter2.4 创建关联2.4 案例 3.在项目中的应用3.1 定义全局使用的logger对象3.2 使用案例 参考 1. logging基础使用 1…