现代 Android 应用通常使用 Kotlin、AndroidX、Jetpack 库和 Jetpack Compose。平台 API 仍位于
android.* 中;AndroidX 在 androidx.* 中提供兼容不同版本且更高层的 API。应用包拥有多个由系统管理的入口点,而不是传统的进程级 main() 方法。
应用隔离 #
Android 为已安装的包分配 Linux UID,并赋予其私有文件基于 UID 的所有权。应用进程运行自己的 Android Runtime 实例,跨包组件调用使用 Binder IPC。运行时权限、SELinux 和框架服务检查会补充 UID 边界。
共享 UID 曾经可供签名相同的包使用,但由于会削弱包隔离,已不再建议新应用使用。应用应通过明确的接口共享数据,例如受权限保护的内容提供程序、文档选择器、URI 授权或 Binder 服务,而不是通过私有路径。
组件和清单 #
Android 有四种组件类型:
- Activity 承载聚焦的用户界面。
- Service 执行没有 Activity UI 的工作。长时间运行且对用户可见的工作需要前台服务通知,并受平台限制。
- Broadcast receiver 对广播执行短暂响应,并应将较长工作委托给适当的调度器。
- Content provider 通过
ContentResolverAPI 暴露结构化数据。
清单声明应用组件、权限、必要时的包可见性、最低 SDK 级别、功能和应用元数据。带有 intent filter 的组件只有在其 android:exported 设置和适用权限允许时,才能被外部寻址。应将非公开组件保持为未导出。
Intent 和组件激活 #
显式 intent 标识特定组件。隐式 intent 描述操作、数据、类别和可选 extras;系统根据已导出的 intent filter 解析它。对于内部操作和服务,应使用显式 intent,因为隐式服务 intent 可能解析到非预期组件。
Activity 通过 startActivity 或 Activity Result API 启动。服务根据其执行模型使用
startService、startForegroundService 或 bindService。不需要立即执行的后台工作应属于 WorkManager,或在适当时属于 JobScheduler,而不是长期运行的后台服务。
将所有传入的 intent、extras 和 URI 视为不可信输入。在 API 允许时验证调用者,验证值,为敏感组件要求权限,并且仅在必要的范围和时间内授予 URI 权限。
Activity 生命周期和状态 #
系统通过 onCreate 创建 Activity,通过 onStart 使其可见,并通过 onResume 使其可交互。onPause 表示 Activity 已失去前台焦点;它必须快速返回。Activity 不再可见时会触发 onStop,这是释放仅在可见期间需要的资源的适当位置。
Activity 可能因为请求了 finish,或因为系统回收其进程而被销毁。对于后一种情况,
onSaveInstanceState 保存少量可重建的 UI 状态。框架会保存受支持的视图层次状态,但应用状态应根据其大小和生命周期存放在 ViewModel、保存状态句柄、数据库或其他持久存储中。不要使用生命周期回调执行无界的网络事务或数据库迁移。
资源 #
Android 资源系统会将 res/ 条目编译为 R.string.app_name 等生成的标识符。将每种资源放在有类型的顶层目录中,例如 layout、drawable、mipmap、values、xml、font、menu、raw、anim 或 animator。放在 assets/ 中的资产不会编译到 R,而是通过 AssetManager 打开。
资源限定符会根据配置、区域设置、屏幕尺寸、密度、方向和夜间模式选择最合适的替代项。限定符必须使用文档规定的顺序,并且不能重复限定符类型。应用引用的每个资源都应保留默认资源,因为设备配置可能与专用替代项不匹配。
Kotlin、Jetpack 和 Compose #
Kotlin 提供空安全、扩展函数、lambda、密封类型和协程。AndroidX 和 Jetpack 提供生命周期感知组件、Navigation、Room、WorkManager 和兼容性 API。lifecycleScope 和 viewModelScope 将协程绑定到其所有者,但取消并不会消除使工作幂等或处理失败的需要。
Jetpack Compose 将 UI 表达为可组合函数。Activity 通过 setContent 进入 Compose;收集到组合中的可观察状态会使受影响的 UI 重新组合。LazyColumn 提供高效的基于项目的布局,修饰符表达布局、交互和装饰。
将屏幕状态保存在 ViewModel 中,使可组合函数主要成为状态的函数,并对生命周期取决于组合的工作使用 effect API。在分阶段迁移期间,Views 和 Compose 可以互操作,因此采用 Compose 不要求重写全部代码。
评论
在 GitHub 上阅读或评论(发表评论需要登录)