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

Android 8.0多线程切换主题正常,Android 11崩溃求助

问题分析与修复方案

崩溃原因

AppCompatDelegate.setDefaultNightMode() 是涉及UI配置变更的操作,必须在主线程执行。Android 11 对主线程操作的校验机制更严格,子线程调用该方法会直接触发崩溃;而 Android 8.0 系统的校验逻辑较宽松,所以没暴露这个问题。另外,子线程中调用 getString()(依赖Context实例)也存在潜在的线程安全风险。

修复代码

把主题切换和SharedPreferences操作全部移回主线程,同时优化代码逻辑:

@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    String[] themeStrings = {"Light","Dark","System Default"};
    ListView lv = requireView().findViewById(R.id.themeChangeLV);
    ArrayAdapter<String> ad = new ArrayAdapter<>(requireContext(), android.R.layout.simple_list_item_1,themeStrings);
    lv.setAdapter(ad);

    sharedPreferences = requireContext().getSharedPreferences("MODE", Context.MODE_PRIVATE);
    nightMODE = sharedPreferences.getBoolean("night",false);

    lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
            SharedPreferences.Editor editor = sharedPreferences.edit();
            switch (i){
                case 0:
                    AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
                    editor.putBoolean(getString(R.string.night),false);
                    editor.putBoolean(getString(R.string.sdt),false);
                    editor.apply();
                    break;
                case 1:
                    AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
                    editor.putBoolean(getString(R.string.night),true);
                    editor.putBoolean(getString(R.string.sdt),false);
                    editor.apply();
                    break;
                case 2:
                    editor.putBoolean(getString(R.string.sdt),true);
                    editor.apply();
                    AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
                    break;
            }
            // 可选:添加平滑过渡减少黑屏感
            if (getActivity() != null) {
                getActivity().overridePendingTransition(0, 0);
                getActivity().recreate();
                getActivity().overridePendingTransition(0, 0);
            }
        }
    });
}

关键修改点

  • 移除所有子线程逻辑,将setDefaultNightMode()和SP编辑操作移至主线程执行
  • 每次点击时重新获取SharedPreferences.Editor,避免复用导致的线程安全问题
  • 补充了"System Default"对应的主题模式设置(原代码漏了这一步)
  • 可选添加overridePendingTransition(0,0)来减少重建Activity时的黑屏闪烁感

额外说明

如果想要进一步优化主题切换的流畅度,可以考虑:

  • 使用ViewModel保存当前页面状态,避免重建后数据丢失
  • 为Activity设置主题切换的过渡动画,替代无动画的重建

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 09:37:55