You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Studio中通过SwitchCompat切换明暗主题时应用崩溃问题求助

Fixing FragmentManager Transaction Crash When Switching Themes With SwitchCompat

Looking at your crash log and code, the issue is a classic timing conflict between theme switching and Fragment transactions. Let's break this down and fix it step by step.

Why the Crash Happens

The error java.lang.IllegalStateException: FragmentManager is already executing transactions tells us everything:

  • When you call AppCompatDelegate.setDefaultNightMode(), the system automatically restarts your Activity to apply the new theme.
  • But your Activity uses a ViewPager2 (evidenced by FragmentStateAdapter and FragmentMaxLifecycleEnforcer in the log), which was in the middle of handling Fragment lifecycle transactions (like destroying or switching Fragments) when the restart was triggered. These two concurrent operations clash, causing FragmentManager to throw an exception.

Solutions

We need to make sure the Activity restart happens after all pending Fragment transactions are completed. Here are two solid approaches:

Approach 1: Delay the Activity Restart

Use a Handler to post the restart action to the end of the main thread's message queue, giving FragmentManager time to finish its current work:

switchCompat.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    @Override
    public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
        // Set the target night mode
        int targetNightMode = isChecked ? AppCompatDelegate.MODE_NIGHT_YES : AppCompatDelegate.MODE_NIGHT_NO;
        AppCompatDelegate.setDefaultNightMode(targetNightMode);
        
        // Delay restart by 100ms to let Fragment transactions finish
        new Handler(Looper.getMainLooper()).postDelayed(() -> {
            recreate();
        }, 100);
    }
});

Approach 2: Execute Pending Transactions First

Force FragmentManager to finish all pending transactions before triggering the theme switch and restart:

switchCompat.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
    @Override
    public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
        // Finish all pending Fragment transactions first
        getSupportFragmentManager().executePendingTransactions();
        
        // Set night mode and restart
        int targetNightMode = isChecked ? AppCompatDelegate.MODE_NIGHT_YES : AppCompatDelegate.MODE_NIGHT_NO;
        AppCompatDelegate.setDefaultNightMode(targetNightMode);
        recreate();
    }
});

Bonus Optimizations

  • Ensure your light/dark themes inherit from a night-mode-compatible base theme to avoid unexpected behavior:
    <!-- Light Theme -->
    <style name="Theme_Light" parent="Theme.MaterialComponents.DayNight.Light.NoActionBar">
        <!-- Your custom attributes here -->
    </style>
    
    <!-- Dark Theme -->
    <style name="Theme_Dark" parent="Theme.MaterialComponents.DayNight.Dark.NoActionBar">
        <!-- Your custom attributes here -->
    </style>
    
  • Save the user's theme preference to SharedPreferences and load it in onCreate() to maintain state across app restarts.

内容的提问来源于stack exchange,提问作者Pietro Lelli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 23:09:09