Jetpack Compose 安全关闭 Activity 或 Fragment 总结

Jetpack Compose 安全关闭 Activity 或 Fragment 总结

1. 关闭 Activity

方法 1:直接调用 finish()(推荐)

@Composable
fun CloseActivityButton() {
    val activity = LocalContext.current as? Activity
    Button(onClick = { activity?.finish() }) {
        Text("Close Activity")
    }
}

适用场景
✅ 直接关闭当前 Activity,不触发返回栈逻辑。
✅ 适用于 setContent { ... } 嵌入 Activity 的情况。


方法 2:安全获取 Activity(扩展函数)

// 扩展函数:避免直接强转 Context
fun Context.findActivity(): Activity? {
    var current = this
    while (current is ContextWrapper) {
        if (current is Activity) return current
        current = current.baseContext
    }
    return null
}

@Composable
fun SafeCloseActivityButton() {
    val activity = LocalContext.current.findActivity()
    Button(onClick = { activity?.finish() }) {
        Text("Close Activity (Safe)")
    }
}

适用场景
✅ 避免 ClassCastException,适用于复用代码(如工具类)。
✅ 兼容 Fragment 中的 requireContext()


方法 3:模拟返回键(onBackPressed

@Composable
fun SimulateBackPress() {
    val activity = LocalContext.current as? Activity
    Button(onClick = { activity?.onBackPressed() }) {
        Text("Simulate Back Press")
    }
}

适用场景
✅ 触发 Activity 默认返回逻辑(如先关闭 Dialog 再退出)。
✅ 适用于需要保留返回栈的情况。


2. 关闭 Fragment

方法 1:使用 Navigation Component(推荐)

@Composable
fun CloseFragmentButton(navController: NavController) {
    Button(onClick = { navController.popBackStack() }) {
        Text("Close Fragment")
    }
}

适用场景
✅ 适用于 NavHost 管理的 Fragment 导航栈。
✅ 自动处理返回动画和状态恢复。


方法 2:直接移除 Fragment(动态添加时)

@Composable
fun RemoveFragmentButton() {
    val fragment = LocalLifecycleOwner.current as? Fragment
    Button(
        onClick = {
            fragment?.parentFragmentManager
                ?.beginTransaction()
                ?.remove(fragment)
                ?.commit()
        }
    ) {
        Text("Remove Fragment")
    }
}

适用场景
✅ 动态添加的 Fragment(如 FragmentTransaction.add())。
⚠️ 需确保 FragmentManager 状态安全。


3. 最佳实践对比

场景 推荐方法 注意事项
关闭 Activity activity?.finish() 直接退出,不触发返回栈逻辑。
安全获取 Activity Context.findActivity() 避免 ClassCastException
模拟返回键 activity?.onBackPressed() 触发 FragmentDialog 先关闭。
关闭 Fragment(Nav) navController.popBackStack() 需依赖 Navigation 组件。
移除动态 Fragment FragmentTransaction.remove() 手动管理 FragmentManager

4. 完整示例代码

Activity 中调用

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            AppTheme {
                Column {
                    CloseActivityButton()
                    SafeCloseActivityButton()
                    SimulateBackPress()
                }
            }
        }
    }
}

Fragment 中调用

class MyFragment : Fragment() {
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        return ComposeView(requireContext()).apply {
            setContent {
                AppTheme {
                    val navController = rememberNavController()
                    Column {
                        CloseFragmentButton(navController)
                        RemoveFragmentButton()
                    }
                }
            }
        }
    }
}

5. 关键注意事项

  1. 内存泄漏
    • 避免在 LaunchedEffect 或异步回调中直接引用 Activity/Fragment,使用 rememberUpdatedState 保持最新引用。
  2. 导航组件优先
    • 使用 NavController 管理 Fragment 切换,避免手动操作 FragmentManager
  3. 上下文安全
    • 尽量使用 LocalContext.current.findActivity() 替代强转,增强健壮性。

总结

  • Activityfinish()(直接关闭)或 onBackPressed()(模拟返回键)。
  • FragmentNavController.popBackStack()(导航组件)或 FragmentTransaction.remove()(动态管理)。
  • 安全获取 Context → 扩展函数 Context.findActivity() 避免崩溃。

按场景选择最合适的方式,确保代码健壮性和可维护性!

你可能感兴趣的:(Compose,compose)