在古老的 Android
时代,基本上一个 Activity
就代表一个界面,所以开发不需要做选择,但随着技术的迭代与框架的完善,Fragment
的使用成为主流,再进化为 Jetpack
的 navigation
。再到如今越来越火热的 Compose
。同是 Android
开发,可能选择的技术栈已经完全不一致了,所以入门学者也容易眼花缭乱。
纯 Activity 时代
Activity
作为最基础的四大组件之一,使用相对简单:
- 在
AndroidManifest
注册 - 通过
startActivity
或者startActivityForResult
启动,现在也可以通过LauncherForActivityResult
来启动 - 通过
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
的方式,代码编写极其繁琐,所以又诞生了统一接口的路由框架,其主要解决以下几个问题:
- 启动方式的大一统
Navagation
注册表的代码自动生成- 传参的大一统,
Activity
使用Intent
添加参数,Fragment
使用Bundle
- 跨
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
呢?
- 可以根据业务逻辑更好的做数据复用。举个例子,注册流程,可能分成数个界面,最中收集到全部数据,我的做法是用一个
RegActivity
, 每一个环节用RegUserNamePage
、RegAvatarPage
等,数据放在RegActivity
的ViewModel
里供所有Page
使用,就不用数据传来传去了。而注册成功后到新的Activity
, 销毁RegActivity
。 - 某些场景用单独的
Activity
更舒服:- 全屏。 如果会涉及全屏切换,那单独出一个
Activity
就更友好。因为我们设置全屏标志位是相对于Activity
而言的。全屏界面跳转到非全屏界面,非全屏界面跳转全屏界面,如果用单Activity
去维护,那是一件很痛苦的事情。 - 需要用到
Activity
的launchMode
的场景,例如播放器,需要singleTask
之类的模式 - 需要一次性销毁多个
Page
的情况,例如前面注册流程的例子,我注册过程中,用户可以返回到上一个Page
, 但是当注册完成后,那就直接销毁RegActivity
。
- 全屏。 如果会涉及全屏切换,那单独出一个
- 目前
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