Jetpack Compose中全局实现Flexible In-AppUpdate的Snackbar提示
方案实现
核心逻辑是把灵活更新的监听、Snackbar展示能力全收敛到BaseActivity的根Compose节点,业务页面完全无侵入,不需要写任何重复代码。
实现逻辑
- 所有更新相关逻辑(灵活更新启动、下载状态监听、安装触发)统一放在
BaseActivity处理,不下发到业务层 - 在
BaseActivity的setContent根节点创建全局SnackbarHostState,作为全局提示的Snackbar载体 - 用Box作为根容器,下层放置业务页面的
SetComposable()内容,上层放置全局SnackbarHost,保证Snackbar永远显示在所有页面内容的最顶层,不会被子页面布局遮挡 - 在根节点用协程监听AppUpdate的下载状态,检测到更新包下载完成时,自动弹出Snackbar安装提示,用户点击安装按钮时直接触发安装流程
改造后代码
BaseActivity 完整代码
abstract class BaseActivity : ComponentActivity() { @Inject lateinit var appUpdate: AppUpdate override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 灵活更新逻辑统一在基类初始化 appUpdate.setUpdateType(AppUpdateTypes.FLEXIBLE) appUpdate.launchFlexibleUpdate(this) setContent { MyAppTheme { // 全局Snackbar状态宿主 val snackbarHostState = remember { SnackbarHostState() } // 监听更新下载状态,和Activity生命周期绑定 LaunchedEffect(Unit) { appUpdate.updateState.collect { updateState -> // 仅在更新包下载完成时触发提示 if (updateState is UpdateState.Downloaded) { // 避免重复弹出Snackbar if (snackbarHostState.currentSnackbarData == null) { val snackbarResult = snackbarHostState.showSnackbar( message = "新版本已下载完成", actionLabel = "立即安装", duration = SnackbarDuration.Indefinite ) // 处理Snackbar交互事件 when (snackbarResult) { SnackbarResult.ActionPerformed -> { // 触发更新安装流程 appUpdate.startFlexibleInstall() } SnackbarResult.Dismissed -> { // 用户手动关闭无需额外处理,后续状态变更会再次触发 } } } } } } // 根叠层布局,保证Snackbar始终在最上层 Box(modifier = Modifier.fillMaxSize()) { // 业务页面内容,原有逻辑完全不需要改动 SetComposable() // 全局Snackbar宿主固定在底部 SnackbarHost( hostState = snackbarHostState, modifier = Modifier.align(Alignment.BottomCenter) ) } } } } /** * Set the composable content for the screen */ @Composable abstract fun SetComposable() }
业务Activity代码
不需要做任何改动,原有业务逻辑完全不受影响:
@AndroidEntryPoint class HomeActivity : BaseActivity() { private lateinit var navController: NavController @Composable override fun SetComposable() { // 原有页面逻辑,不需要添加任何更新提示、Snackbar相关代码 } }
注意事项
- 用Box替代Scaffold作为根容器,避免子页面使用Scaffold时出现双层内边距、Snackbar被子页面遮挡的问题,完全不侵入子页面的布局实现
- 增加重复弹出判断,避免状态重复回调时弹出多个Snackbar
- 由于每个Activity继承BaseActivity时都会在onCreate阶段初始化状态监听,即使用户在下载过程中切换Activity,进入新页面时如果更新包已经下载完成,会立刻弹出Snackbar,不会出现提示遗漏
- 如果后续有其他全局提示需求(比如全局通知、登录过期提示),可以将
snackbarHostState通过CompositionLocal下发到所有子Composable,复用同一个全局Snackbar载体,减少重复实现
内容的提问来源于stack exchange,提问作者Satyam Gondhale
相关产品推荐
相关产品推荐

