使用DatePickerDialog Fragment时setTargetFragment等方法为何被弃用
相关API弃用原因
setTargetFragment / getTargetFragment 弃用原因
- 该API依赖强引用关联两个Fragment,当Fragment被系统销毁重建(如配置变更、内存不足回收)时,引用会直接失效,甚至触发内存泄漏或空指针崩溃
- 不兼容官方主推的Navigation导航组件,无法在单Activity多Fragment的现代化架构中使用
- 仅支持同个FragmentManager下的Fragment通信,跨FragmentManager场景完全无法生效
onActivityResult 弃用原因
- 该API最早为Activity间数据回传设计,延伸到Fragment场景后存在链路不稳定问题,系统重建后极易出现结果和请求无法匹配的问题
- 需要全局维护唯一请求码,多模块开发时极易出现请求码冲突,导致逻辑混乱
- 请求逻辑和结果处理逻辑分离,代码可读性差,后期维护成本高
适配方案(官方推荐Fragment Result API)
针对你的日期选择场景,仅需修改几处代码即可完成适配:
1. 修改FragmentAggiungiPaziente逻辑
首先在onCreateView方法中注册结果接收器,删除原有setTargetFragment调用和onActivityResult方法:
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { view = inflater.inflate(R.layout.fragment_aggiungi_paziente, container, false); // ... 原有初始化逻辑不变 // 新增:注册日期选择结果接收器 getParentFragmentManager().setFragmentResultListener("DATE_PICKER_RESULT", this, (requestKey, result) -> { String selectedDate = result.getString("selectedDate"); dataPaz.setText(selectedDate); }); dataPaz.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { FragmentData newFragment = new FragmentData(); // 删掉原来的setTargetFragment调用 newFragment.show(fm, "datePicker"); } }); // ... 剩余原有逻辑不变 } // 删掉原有onActivityResult方法
2. 修改FragmentData逻辑
修改onDateSet方法,删除原有getTargetFragment相关调用,直接通过Fragment Result API回传数据:
@Override public void onDateSet(DatePicker datePicker, int i, int i1, int i2) { c.set(Calendar.YEAR, i); c.set(Calendar.MONTH, i1); c.set(Calendar.DAY_OF_MONTH, i2); String selectedDate = new SimpleDateFormat("dd/MM/yyyy", Locale.ITALIAN).format(c.getTime()); // 封装结果发送 Bundle result = new Bundle(); result.putString("selectedDate", selectedDate); getParentFragmentManager().setFragmentResult("DATE_PICKER_RESULT", result); dismiss(); }
该方案无需持有Fragment强引用,系统重建后会自动恢复结果接收逻辑,不会出现内存泄漏或数据丢失问题,同时适配所有现代Fragment使用场景。
内容的提问来源于stack exchange,提问作者Pasquale Serra
相关产品推荐
相关产品推荐

