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

如何在Adapter中通过Dialog更新数据后刷新RecyclerView

问题描述

我的应用需要通过弹窗(Dialog)更新和删除RecyclerView中的条目,弹窗在点击弹出菜单(PopupMenu)后打开。我已经在Adapter类的onBindViewHolder方法中实现了弹窗功能,且服务器端的数据更新与删除操作已成功完成,请问如何在此操作后刷新RecyclerView?

Adapter.java 核心代码

holder.cBtnMore.setOnClickListener(v -> {
    PopupMenu popupMenu = new PopupMenu(v.getContext(), holder.cBtnMore);
    popupMenu.getMenuInflater().inflate(R.menu.more_menu, popupMenu.getMenu());

    popupMenu.setOnMenuItemClickListener(menuItem -> {
        if (menuItem.getItemId() == R.id.menu_update) {
            final Dialog dialog = new Dialog(v.getContext());
            dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
            dialog.setContentView(R.layout.dialog_update);
            dialog.getWindow().setLayout(Cons.widthScreen, Cons.heightScreen);

            // 控件声明与文本设置...

            btnUpdate.setOnClickListener(unused -> {
                updateBarang(
                        v.getContext(),
                        id,
                        etNama.getText().toString(),
                        etAlamat.getText().toString(),
                        etNoPenjual.getText().toString(),
                        etKodeBarang.getText().toString(),
                        etJumlahPenjualan.getText().toString(),
                        etHargaSatuan.getText().toString(),
                        etDiskon.getText().toString(),
                        etTotalHarga.getText().toString()
                );
            });

            btnCancel.setOnClickListener(unused -> {
                dialog.dismiss();
            });

            dialog.show();
        } else if (menuItem.getItemId() == R.id.menu_delete) {
            Toast.makeText(v.getContext(), "Delete", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(v.getContext(), "Error", Toast.LENGTH_SHORT).show();
        }

        return true;
    });

    popupMenu.show();
});

MainActivity.java 核心代码

public class MainActivity extends AppCompatActivity {

    FloatingActionButton fabAdd;
    RecyclerView rvBarang;
    ApiInterface apiInterface;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        apiInterface = ApiConnection.Connection().create(ApiInterface.class);

        // ...其他初始化代码

        rvBarang.setLayoutManager(new LinearLayoutManager(this));
    }

    @Override
    protected void onResume() {
        Call<List<Barang>> tampilBarang = apiInterface.listBarang();
        tampilBarang.enqueue(new Callback<List<Barang>>() {
            @Override
            public void onResponse(Call<List<Barang>> call, Response<List<Barang>> response) {
                ArrayList<Barang> barangArrayList = (ArrayList<Barang>) response.body();
                BarangAdapter barangAdapter = new BarangAdapter(barangArrayList);
                rvBarang.setAdapter(barangAdapter);
            }

            @Override
            public void onFailure(Call<List<Barang>> call, Throwable t) {
                // TODO 处理请求失败
            }
        });
        super.onResume();
    }
}

解决方案

方法一:更新本地数据集+局部刷新(推荐)

这种方式无需重新请求服务器,效率更高,是RecyclerView刷新的最佳实践。

1. 改造Adapter,添加数据操作方法

在BarangAdapter中保留数据集引用,并实现更新、删除单条数据的方法:

public class BarangAdapter extends RecyclerView.Adapter<BarangAdapter.ViewHolder> {
    private ArrayList<Barang> mBarangList;

    public BarangAdapter(ArrayList<Barang> barangList) {
        this.mBarangList = barangList;
    }

    // 更新指定位置的条目
    public void updateItem(int position, Barang updatedBarang) {
        mBarangList.set(position, updatedBarang);
        notifyItemChanged(position); // 仅刷新目标条目,性能更优
    }

    // 删除指定位置的条目
    public void removeItem(int position) {
        mBarangList.remove(position);
        notifyItemRemoved(position);
        // 通知后续条目位置更新
        notifyItemRangeChanged(position, mBarangList.size() - position);
    }

    // 获取数据集(供外部调用)
    public ArrayList<Barang> getBarangList() {
        return mBarangList;
    }

    // 原有ViewHolder、onCreateViewHolder等代码...
}

2. 改造MainActivity,全局持有Adapter和数据集

将Adapter和数据集设为全局变量,方便后续操作:

public class MainActivity extends AppCompatActivity {
    FloatingActionButton fabAdd;
    RecyclerView rvBarang;
    ApiInterface apiInterface;
    private BarangAdapter barangAdapter;
    private ArrayList<Barang> barangArrayList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        apiInterface = ApiConnection.Connection().create(ApiInterface.class);
        rvBarang.setLayoutManager(new LinearLayoutManager(this));
    }

    @Override
    protected void onResume() {
        super.onResume();
        fetchBarangData();
    }

    // 封装数据请求方法
    public void fetchBarangData() {
        Call<List<Barang>> tampilBarang = apiInterface.listBarang();
        tampilBarang.enqueue(new Callback<List<Barang>>() {
            @Override
            public void onResponse(Call<List<Barang>> call, Response<List<Barang>> response) {
                barangArrayList = (ArrayList<Barang>) response.body();
                barangAdapter = new BarangAdapter(barangArrayList);
                rvBarang.setAdapter(barangAdapter);
            }

            @Override
            public void onFailure(Call<List<Barang>> call, Throwable t) {
                // 处理请求失败逻辑,比如弹出Toast
            }
        });
    }

    // 提供外部访问Adapter的方法
    public BarangAdapter getBarangAdapter() {
        return barangAdapter;
    }

    public ArrayList<Barang> getBarangArrayList() {
        return barangArrayList;
    }
}

3. 更新操作:服务器成功后同步本地数据

在updateBarang方法的网络请求成功回调中,更新本地数据集并通知Adapter:

private void updateBarang(Context context, String id, String nama, String alamat, String noPenjual, String kodeBarang, String jumlahPenjualan, String hargaSatuan, String diskon, String totalHarga) {
    apiInterface.updateBarang(id, nama, alamat, noPenjual, kodeBarang, jumlahPenjualan, hargaSatuan, diskon, totalHarga)
            .enqueue(new Callback<ResponseBody>() {
                @Override
                public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                    if (response.isSuccessful()) {
                        MainActivity activity = (MainActivity) context;
                        // 找到目标条目的位置
                        int targetPosition = -1;
                        for (int i = 0; i < activity.getBarangArrayList().size(); i++) {
                            if (activity.getBarangArrayList().get(i).getId().equals(id)) {
                                targetPosition = i;
                                break;
                            }
                        }
                        if (targetPosition != -1) {
                            // 创建更新后的Barang对象
                            Barang updatedBarang = new Barang();
                            updatedBarang.setId(id);
                            updatedBarang.setNama(nama);
                            updatedBarang.setAlamat(alamat);
                            updatedBarang.setNoPenjual(noPenjual);
                            updatedBarang.setKodeBarang(kodeBarang);
                            updatedBarang.setJumlahPenjualan(jumlahPenjualan);
                            updatedBarang.setHargaSatuan(hargaSatuan);
                            updatedBarang.setDiskon(diskon);
                            updatedBarang.setTotalHarga(totalHarga);
                            // 通知Adapter更新条目
                            activity.getBarangAdapter().updateItem(targetPosition, updatedBarang);
                        }
                        // 关闭弹窗
                        dialog.dismiss();
                        Toast.makeText(context, "更新成功", Toast.LENGTH_SHORT).show();
                    }
                }

                @Override
                public void onFailure(Call<ResponseBody> call, Throwable t) {
                    Toast.makeText(context, "更新失败", Toast.LENGTH_SHORT).show();
                }
            });
}

4. 删除操作:服务器成功后移除本地条目

在PopupMenu的删除分支中,获取条目位置并发起删除请求,成功后同步本地数据:

else if (menuItem.getItemId() == R.id.menu_delete) {
    int position = holder.getAdapterPosition();
    // 检查位置有效性,避免条目已被回收
    if (position != RecyclerView.NO_POSITION) {
        Barang targetBarang = barangAdapter.getBarangList().get(position);
        String id = targetBarang.getId();
        // 发起删除请求
        apiInterface.deleteBarang(id).enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                if (response.isSuccessful()) {
                    MainActivity activity = (MainActivity) v.getContext();
                    activity.getBarangAdapter().removeItem(position);
                    Toast.makeText(v.getContext(), "删除成功", Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                Toast.makeText(v.getContext(), "删除失败", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

方法二:重新请求服务器数据(简单但效率低)

如果不想维护本地数据集的同步,可以在服务器操作成功后,重新调用数据请求方法刷新整个列表:

在更新/删除的成功回调中,调用MainActivity的fetchBarangData方法:

// 更新成功回调示例
if (response.isSuccessful()) {
    dialog.dismiss();
    ((MainActivity)context).fetchBarangData();
    Toast.makeText(context, "更新成功", Toast.LENGTH_SHORT).show();
}

注意事项

  • 优先使用方法一的局部刷新,避免notifyDataSetChanged()(会刷新整个列表,性能差)。
  • 必须在主线程调用Adapter的通知方法(网络回调默认在子线程,若需要可通过runOnUiThread切换)。
  • 获取条目位置时,务必检查position != RecyclerView.NO_POSITION,防止条目已被回收导致的异常。

内容的提问来源于stack exchange,提问作者Koh Endru

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 17:35:30