Android Studio中通过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
FragmentStateAdapterandFragmentMaxLifecycleEnforcerin 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
SharedPreferencesand load it inonCreate()to maintain state across app restarts.
内容的提问来源于stack exchange,提问作者Pietro Lelli

