DialogFragment向Fragment传递删除回调刷新RecyclerView实现方法
Fragment Result API 实现书籍删除回调正确方案
必须遵守的实现规则
- 禁止在
BookDialogFragment中手动新建BookFragment实例,该操作会生成全新的Fragment对象,和当前屏幕上显示的宿主实例完全无关,必然无法触发原有列表的刷新 - 结果监听器必须在
BookFragment的onViewCreated/onCreate生命周期注册,绑定视图生命周期所有者,避免重复注册或内存泄漏 - 弹窗和宿主必须使用同一个
FragmentManager传递结果,requestKey必须完全匹配,否则结果无法正常派发 - 所有跨组件传递的参数(书籍ID、列表位置)必须通过
Bundle序列化传递,禁止直接持有对象引用,避免屏幕旋转重建时出现空指针或内存泄漏
各文件修改代码
BookDialogFragment.java
public class BookDialogFragment extends DialogFragment { // 统一定义通信常量,避免硬编码拼写错误 public static final String REQUEST_KEY_DELETE = "delete_book_request"; public static final String ARG_BOOK_ID = "arg_book_id"; public static final String ARG_BOOK_POSITION = "arg_book_position"; @NonNull @Override public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { Bundle args = getArguments(); long currentBookId = args != null ? args.getLong(ARG_BOOK_ID, -1L) : -1L; int currentPosition = args != null ? args.getInt(ARG_BOOK_POSITION, -1) : -1; return new AlertDialog.Builder(requireContext()) .setTitle("删除确认") .setMessage("确定要删除该书籍吗?操作不可恢复") .setPositiveButton("确认删除", (dialog, which) -> { // 点击确认时直接派发结果,不需要持有宿主引用 Bundle resultBundle = new Bundle(); resultBundle.putLong(ARG_BOOK_ID, currentBookId); resultBundle.putInt(ARG_BOOK_POSITION, currentPosition); getParentFragmentManager().setFragmentResult(REQUEST_KEY_DELETE, resultBundle); dismiss(); }) .setNegativeButton("取消", (dialog, which) -> dismiss()) .create(); } // 静态工厂方法传参,保证屏幕旋转时参数不丢失 public static BookDialogFragment newInstance(long bookId, int position) { Bundle args = new Bundle(); args.putLong(ARG_BOOK_ID, bookId); args.putInt(ARG_BOOK_POSITION, position); BookDialogFragment dialog = new BookDialogFragment(); dialog.setArguments(args); return dialog; } }
BookFragment.java
public class BookFragment extends Fragment { private BookAdapter bookAdapter; private List<Book> bookDataList; private RecyclerView recyclerView; @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); // 原有RecyclerView、adapter初始化逻辑保留 initRecyclerView(); // 注册删除结果监听器,绑定视图生命周期,和弹窗使用同一个FragmentManager getParentFragmentManager().setFragmentResultListener( BookDialogFragment.REQUEST_KEY_DELETE, getViewLifecycleOwner(), (requestKey, result) -> { long deleteBookId = result.getLong(BookDialogFragment.ARG_BOOK_ID, -1L); int deletePosition = result.getInt(BookDialogFragment.ARG_BOOK_POSITION, -1); if (deleteBookId != -1 && deletePosition != -1) { removeBook(deleteBookId, deletePosition); } } ); } // 原有removeBook方法补全刷新逻辑 private void removeBook(long bookId, int position) { // 1. 从本地数据库/数据源删除书籍 BookRepository.getInstance(requireContext()).deleteBookById(bookId); // 2. 移除内存列表中对应项 bookDataList.remove(position); // 3. 定向刷新列表,性能优于全局刷新 bookAdapter.notifyItemRemoved(position); // 修正后续列表项的位置,避免角标错乱 bookAdapter.notifyItemRangeChanged(position, bookDataList.size() - position); } }
BookAdapter.java / BookViewHolder.java
在列表项删除按钮的点击逻辑中,通过静态方法创建弹窗,使用宿主Fragment的childFragmentManager弹出,不要自行创建Fragment实例:
// 列表项删除按钮点击逻辑 deleteBtn.setOnClickListener(v -> { int currentPos = getBindingAdapterPosition(); if (currentPos == RecyclerView.NO_POSITION) return; Book targetBook = dataList.get(currentPos); BookDialogFragment deleteDialog = BookDialogFragment.newInstance(targetBook.getId(), currentPos); // 直接传入宿主BookFragment的childFragmentManager即可,不要新建设置Fragment实例 deleteDialog.show(hostBookFragment.getChildFragmentManager(), "delete_book_dialog"); });
回调不触发排查清单
- 检查
setFragmentResult和setFragmentResultListener调用的FragmentManager是否完全一致,不要混用Activity的supportFragmentManager和Fragment的childFragmentManager - 检查两边使用的requestKey字符串是否完全一致,优先使用类中定义的静态常量,禁止两边硬编码
- 监听器的LifecycleOwner必须传入
getViewLifecycleOwner(),不要传入Fragment实例本身,避免视图销毁后回调异常 - 弹窗弹出时不要使用
new BookDialogFragment()直接构造后传参,必须走newInstance()方法通过Bundle传值,避免参数丢失
内容的提问来源于stack exchange,提问作者Guilherme Hepfener
相关产品推荐
相关产品推荐

