setTargetFragment已废弃时如何正确使用PreferenceDialogFragmentCompat
问题根本原因
你反编译得到的校验逻辑完全正确,截至androidx.preference:1.2.0版本,PreferenceDialogFragmentCompat仍然硬编码要求目标Fragment必须实现TargetFragment接口(该接口已经由PreferenceFragmentCompat默认实现),且内部逻辑依赖getTargetFragment()获取关联的Preference实例,你移除setTargetFragment()调用后校验直接失败抛出异常。
另外你误用了replace事务加载DialogFragment,DialogFragment本身是弹窗容器,应该调用自带的show()方法展示,不需要替换布局容器。
可选解决方案
方案1:临时保留setTargetFragment(短期兼容首选)
setTargetFragment只是被标记为废弃,官方不会在现有稳定版系统/依赖库中直接移除该API,且PreferenceDialogFragmentCompat本身的内部逻辑仍依赖该API,因此你可以暂时保留原有调用,等待官方preference库后续版本适配Fragment Result API后再做修改,不会影响现有应用的正常运行。
方案2:自定义DialogFragment适配Fragment Result API(长期合规方案)
重写你的自定义PreferenceDialogFragmentCompat子类,跳过原有target校验逻辑,改用Fragment Result API传递选择结果,具体实现如下:
- 改造自定义DialogFragment:
public class NumberPickerPreferenceDialogFragment extends PreferenceDialogFragmentCompat { public static NumberPickerPreferenceDialogFragment newInstance(String key) { NumberPickerPreferenceDialogFragment fragment = new NumberPickerPreferenceDialogFragment(); Bundle args = new Bundle(); args.putString(ARG_KEY, key); fragment.setArguments(args); return fragment; } @Override public void onCreate(Bundle savedInstanceState) { // 跳过父类的targetFragment校验逻辑,自己处理结果返回 super.onCreate(savedInstanceState); } @Override public void onDialogClosed(boolean positiveResult) { if (positiveResult) { int selectedValue = 你选择的数值; Bundle result = new Bundle(); result.putInt("selected_value", selectedValue); // 把结果返回给宿主Fragment getParentFragmentManager().setFragmentResult("number_picker_result", result); } } }
- 修改PreferenceFragmentCompat中的调用逻辑:
@Override public void onDisplayPreferenceDialog(Preference preference) { if (getParentFragmentManager().findFragmentByTag(DIALOG_FRAGMENT_TAG) != null) { return; } final DialogFragment f; if (preference instanceof NumberPickerPreference) { f = NumberPickerPreferenceDialogFragment.newInstance(preference.getKey()); // 注册结果监听接收选择值 getParentFragmentManager().setFragmentResultListener("number_picker_result", this, (requestKey, result) -> { int selectedValue = result.getInt("selected_value"); // 同步更新Preference的存储值和展示状态 SharedPreferences.Editor editor = preference.getSharedPreferences().edit(); editor.putInt(preference.getKey(), selectedValue); editor.apply(); preference.setSummary(String.valueOf(selectedValue)); }); } else if (preference instanceof TextAutoCompletePreference) { // 按照相同逻辑改造TextAutoCompletePreferenceDialogFragment即可 f = TextAutoCompletePreferenceDialogFragment.newInstance(preference.getKey()); } else { f = null; } if (f != null) { // 直接调用show方法展示弹窗,不需要调用setTargetFragment f.show(getParentFragmentManager(), DIALOG_FRAGMENT_TAG); } else { super.onDisplayPreferenceDialog(preference); } }
内容的提问来源于stack exchange,提问作者hushed_voice
相关产品推荐
相关产品推荐

