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

如何存储registerForActivityResult返回值?遇SharedPreferences与Fragment静态冲突

解决方案

核心问题分析

  • PreferenceFragmentCompat作为Activity的内部类必须声明为static,否则系统重建Fragment时会抛出IllegalStateException——非静态内部类依赖外部Activity实例,无法独立完成重建
  • 静态内部类无法直接调用getApplicationContext(),但可以通过Fragment的getActivity()方法,在Fragment成功依附Activity后获取有效上下文

具体修改步骤

  1. 将SettingsFragment改为static内部类(满足系统重建的硬性要求)
  2. 把registerForActivityResult的初始化移到Fragment的onCreate方法——Fragment的registerForActivityResult必须在生命周期早期调用,不能直接作为成员变量初始化
  3. 用getActivity()获取上下文操作SharedPreferences——确保在Fragment已绑定Activity时调用,避免空指针
  4. (推荐)使用PreferenceManager.getDefaultSharedPreferences()获取和设置页关联的SharedPreferences实例,比手动指定文件名更符合Android设置页设计规范

修改后的完整代码

public class SettingsActivity extends AppCompatActivity
        implements SharedPreferences.OnSharedPreferenceChangeListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.settings_activity);
        if (savedInstanceState == null) {
            getSupportFragmentManager()
                    .beginTransaction()
                    .replace(R.id.settings, new SettingsFragment())
                    .commit();
        }
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        // 保留你的原有业务逻辑
    }

    // 改为static内部类
    public static class SettingsFragment extends PreferenceFragmentCompat {
        private ActivityResultLauncher<String> mGetContent;

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            // 在onCreate中初始化ActivityResultLauncher
            mGetContent = registerForActivityResult(
                    new ActivityResultContracts.GetContent(),
                    uri -> {
                        if (uri == null) return; // 处理用户取消选择的情况
                        Log.i("MYAPP", "File selected:" + uri.toString());

                        // 空指针防护,确保Fragment已绑定Activity
                        if (getActivity() == null) return;
                        // 获取设置页对应的SharedPreferences
                        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
                        SharedPreferences.Editor editor = sharedPreferences.edit();
                        editor.putString("audio_filename", uri.toString());
                        editor.apply();
                    });
        }

        @Override
        public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
            setPreferencesFromResource(R.xml.root_preferences, rootKey);
        }

        @Override
        public boolean onPreferenceTreeClick(Preference preference) {
            String key = preference.getKey();
            if ("audio_filename".equals(key)) {
                mGetContent.launch("audio/*"); // 建议限定为音频类型,而非*/*
                return true;
            }
            return super.onPreferenceTreeClick(preference);
        }
    }
}

关键细节说明

  • static内部类:既满足系统重建Fragment的要求,又避免了静态类持有外部Activity隐式引用导致的内存泄漏
  • registerForActivityResult初始化时机:放在onCreate是最安全的生命周期节点,确保Fragment初始化完成后注册回调
  • 空指针防护:添加getActivity() == null的判断,避免Fragment未依附Activity时触发的异常
  • SharedPreferences选型:PreferenceManager.getDefaultSharedPreferences()会自动关联应用默认的设置偏好文件,无需手动指定文件名

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 20:01:54