Android 13+中使用registerOnBackInvokedCallback替代super.onBackPressed()的正确方法
适配Android 13+返回键的正确实现
你在OnBackInvokedCallback中调用getOnBackPressedDispatcher().onBackPressed()是错误的,这会触发无限循环——因为API 33+中onBackPressed()会直接触发你注册的OnBackInvokedCallback,导致回调反复执行,最终抛出StackOverflowError。
原代码逻辑的正确替代
你原来的代码逻辑是:设置标记dontStopMusicOnPause = true,再执行系统默认返回操作(优先弹出Fragment回退栈,无回退栈则关闭Activity)。对应OnBackInvokedCallback的正确写法如下:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { OnBackInvokedCallback callback = () -> { // 执行自定义标记逻辑 dontStopMusicOnPause = true; // 完全模拟super.onBackPressed()的默认行为 if (getSupportFragmentManager().getBackStackEntryCount() > 0) { // 存在Fragment回退栈,弹出顶部Fragment getSupportFragmentManager().popBackStack(); } else { // 无回退栈,关闭当前Activity finish(); } }; getOnBackInvokedDispatcher().registerOnBackInvokedCallback( OnBackInvokedDispatcher.PRIORITY_DEFAULT, callback ); // 绑定生命周期注销回调,避免内存泄漏 getLifecycle().addObserver(new DefaultLifecycleObserver() { @Override public void onDestroy(@NonNull LifecycleOwner owner) { getOnBackInvokedDispatcher().unregisterOnBackInvokedCallback(callback); } }); }
为什么不能直接调用finish()?
直接调用finish()会跳过Fragment回退栈的处理,而原super.onBackPressed()会优先处理Fragment回退逻辑,只有当栈为空时才会关闭Activity。上面的代码完整复现了这一系统默认行为。
低版本兼容方案
如果需要兼容Android 12及以下版本,保留原onBackPressed()实现即可,系统会自动在低版本走旧逻辑,高版本走OnBackInvokedCallback:
@Override public void onBackPressed() { dontStopMusicOnPause = true; super.onBackPressed(); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ...其他初始化代码 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { OnBackInvokedCallback callback = () -> { dontStopMusicOnPause = true; if (getSupportFragmentManager().getBackStackEntryCount() > 0) { getSupportFragmentManager().popBackStack(); } else { finish(); } }; getOnBackInvokedDispatcher().registerOnBackInvokedCallback( OnBackInvokedDispatcher.PRIORITY_DEFAULT, callback ); getLifecycle().addObserver(new DefaultLifecycleObserver() { @Override public void onDestroy(@NonNull LifecycleOwner owner) { getOnBackInvokedDispatcher().unregisterOnBackInvokedCallback(callback); } }); } }
内容的提问来源于stack exchange,提问作者NullPointerException
相关产品推荐
相关产品推荐

