如何存储registerForActivityResult返回值?遇SharedPreferences与Fragment静态冲突
解决方案
核心问题分析
- PreferenceFragmentCompat作为Activity的内部类必须声明为
static,否则系统重建Fragment时会抛出IllegalStateException——非静态内部类依赖外部Activity实例,无法独立完成重建 - 静态内部类无法直接调用
getApplicationContext(),但可以通过Fragment的getActivity()方法,在Fragment成功依附Activity后获取有效上下文
具体修改步骤
- 将SettingsFragment改为static内部类(满足系统重建的硬性要求)
- 把registerForActivityResult的初始化移到Fragment的onCreate方法——Fragment的registerForActivityResult必须在生命周期早期调用,不能直接作为成员变量初始化
- 用getActivity()获取上下文操作SharedPreferences——确保在Fragment已绑定Activity时调用,避免空指针
- (推荐)使用
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
相关产品推荐
相关产品推荐

