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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 12:15:43