多 Activity 多 Page 的 UI 架构

在古老的 Android 时代,基本上一个 Activity 就代表一个界面,所以开发不需要做选择,但随着技术的迭代与框架的完善,Fragment 的使用成为主流,再进化为 Jetpack 的 navigation。再到如今越来越火热的 Compose。同是 Android 开发,可能选择的技术栈已经完全不一致了,所以入门学者也容易眼花缭乱。

纯 Activity 时代

Activity 作为最基础的四大组件之一,使用相对简单:

  1. 在 AndroidManifest 注册
  2. 通过 startActivity 或者 startActivityForResult 启动,现在也可以通过 LauncherForActivityResult 来启动
  3. 通过 finish 结束 Activity

其主要的问题就是需要在 AndroidManifest 中注册,开发过程中容易忘记。若需要做 patch、插件化等功能,就必须搞一些 HolderActivity 预注册,也是相当麻烦的。

除此之外,它本身是一个很重的组件,启动一个 Activity 就会有跨进程的操作,比较耗时。除此之外,动画控制也不是那么的灵活。

Fragment 入场

Fragment 原本是为了给平板使用的,最简单的例子就是列表-详情,手机端是列表界面点击进入详情界面,而平板则可以左侧列表,右侧详情。

但随着 Fragment 的发展,因为其灵活性,它反而成了界面开发的主角,造就了单 Activity 多 Fragment 架构。

单 Activity 多 Fragment 架构。 Activity 就是一个承载 Fragment 的容器,所有的界面由 Fragment 承载,由于 Fragment 的事务型启动很繁琐,所以官方又出品了 Navigation 库来解决这个问题。但 Navigation 库需要创建并注册 Graph,也是一个繁琐的事情。

路由框架入场

Activity 与 Fragment/Navigation 的启动新界面的方式各不相同, Navigation 还有一个创建 Graph 的方式,代码编写极其繁琐,所以又诞生了统一接口的路由框架,其主要解决以下几个问题:

  1. 启动方式的大一统
  2. Navagation 注册表的代码自动生成
  3. 传参的大一统,Activity 使用 Intent添加参数, Fragment 使用 Bundle
  4. 跨 module 的界面启动(模块化需求)

由于官方没有出品,所以就是由各个业务职能部门创建,诸如:ARouter、TheRouter、QMUI Scheme、Emo Scheme 等库。

ARouter 与 TheRouter 偏向于模块化。

而个人开发的 QMUI Scheme 与 Emo Scheme 则没有支持模块化,而是在多 Activity 多 Page 的支持上花费了很大工费。这里一个 Page 可以是Fragment 也可以是 Compose。

多 Activity 多 Page 架构是指我们可以使用多个 Activity, 每个 Activity 都可以是多 Page 的存在, 具体是否要使用 Activity, 则由开发根据业务逻辑决定。

QMUI Scheme 支持了多 Activty 多 Fragment 架构。

Emo Scheme 支持了多 Activity 多 Compose 架构。

这是二者的差异,在 Emo Scheme 开发时,我觉得 Compose 诞生后,Fragment 就是一个鸡肋的存在了,所以现在我就完全抛弃它了。

那为何要采取多 Activity 多 Page 呢?

  1. 可以根据业务逻辑更好的做数据复用。举个例子,注册流程,可能分成数个界面,最中收集到全部数据,我的做法是用一个 RegActivity, 每一个环节用 RegUserNamePage、RegAvatarPage 等,数据放在 RegActivity 的 ViewModel 里供所有 Page 使用,就不用数据传来传去了。而注册成功后到新的 Activity, 销毁 RegActivity。
  2. 某些场景用单独的 Activity 更舒服:
    • 全屏。 如果会涉及全屏切换,那单独出一个 Activity 就更友好。因为我们设置全屏标志位是相对于 Activity 而言的。全屏界面跳转到非全屏界面,非全屏界面跳转全屏界面,如果用单 Activity 去维护,那是一件很痛苦的事情。
    • 需要用到 Activity 的 launchMode 的场景,例如播放器,需要 singleTask 之类的模式
    • 需要一次性销毁多个 Page 的情况,例如前面注册流程的例子,我注册过程中,用户可以返回到上一个 Page, 但是当注册完成后,那就直接销毁 RegActivity。
  3. 目前 Compose 里嵌套 WebView,Navigation 转场动画效果有点差,所以我是选择用 Activity 去承载。

总而言之,之所以把框架做得这么复杂,就是期望开发能够认真思考业务流程,要根据我们的业务流程认真的考虑我们该以什么样的容器去承载我们的界面更合适。选择正确,往往能取到事半功倍的效果。

目前而言,Emo Scheme 是所有路由框架中对这一块中支持得最好的,具体使用方法可以前往 官网 了解。

最后

世上没有最好的架构,只有最适合自己的。UI 往往是变动最频繁的业务,所以了解各个组件的优缺点,根据业务逻辑去选用最适合的,才是高效开发的捷径。不管怎样,都是有无数坑点的,趋利避害才是 UI 的归宿。UI 最好的经验就是知道各个组件有什么坑点,如何避开。不然随便一个坑,就够开发加好一会儿班了。

Android 学习笔录

Android 性能优化篇:https://qr18.cn/FVlo89

Android Framework底层原理篇:https://qr18.cn/AQpN4J

Android 车载篇:https://qr18.cn/F05ZCM

Android 逆向安全学习笔记:https://qr18.cn/CQ5TcL

Android 音视频篇:https://qr18.cn/Ei3VPD

Jetpack全家桶篇(内含Compose):https://qr18.cn/A0gajp

OkHttp 源码解析笔记:https://qr18.cn/Cw0pBD

Kotlin 篇:https://qr18.cn/CdjtAF

Gradle 篇:https://qr18.cn/DzrmMB

Flutter 篇:https://qr18.cn/DIvKma

Android 八大知识体:https://qr18.cn/CyxarU

Android 核心笔记:https://qr21.cn/CaZQLo

Android 往年面试题锦:https://qr18.cn/CKV8OZ

2023年最新Android 面试题集:https://qr18.cn/CgxrRy

Android 车载开发岗位面试习题:https://qr18.cn/FTlyCJ

音视频面试题锦:https://qr18.cn/AcV6Ap

相关推荐
海姐软件测试7 小时前
IT疑难杂症诊疗室:从故障现象到根因定位的实战指南
架构
小七在进步7 小时前
C++内存管理:new/delete vs malloc/free深度解析
android·java·c++
mldong7 小时前
工作流引擎的委托代批:一张单,两个办理人
后端·架构
Joy T13 小时前
Agent 确定性上下文设计:从 Prompt 参数注入到能力分层
java·开发语言·微服务·架构·prompt·agent context
微订校园外卖平台15 小时前
同城外卖小程序开发:校园外卖系统四端架构与订单链路拆解
架构·外卖系统·本地生活·微订
m0_5873830016 小时前
广州 24 小时自助健身房解决方案技术实现与实战指南
java·spring·小程序·架构·需求分析
牛战士coding16 小时前
AI Agent 如何接入真实业务系统?订单助手三层架构完整拆解
人工智能·架构
收放扳机16 小时前
PCB收放板设备机械手架构选型参考——三轴/四轴/六轴/蜘蛛手对比
人工智能·科技·架构·自动化·制造·pcb工艺
九卷17 小时前
企业级Agent系统整体技术架构介绍
ai·架构·大模型·llm·agent·智能体
木子n118 小时前
软件架构设计实战-架构18.从Classic到Adaptive:SOA架构在MATLAB里的模样
架构·autosar·性能工程·服务化架构