【问题标题】:RecyclerView not updateRecyclerView 不更新
【发布时间】:2020-06-18 12:27:51
【问题描述】:

我的 MainActivity 有一个 recyclerview 将接收产品。在 MainActivity 的 floatActionButton 中,我调用 AddActivity ,它具有添加产品的字段,包括一个回收器,我在其中插入输入以构成价格。问题正是在 AddActivity recyclerView

我有一个简单的 recyclerView 和下面的适配器,我在保存到数据库之前在其中执行 CRUD,除了更新之外一切正常,我通过适配器更新项目,但列表中的视图不更新数据。如果您单击同一项目再次对其进行编辑,则会显示已更新的值,而不是列表中显示的值。

在我的适配器下方:

public class InsumoAdapter extends RecyclerView.Adapter<InsumoAdapter.InsumoViewHolder>{

   
    private final Context context;
    private List<Insumo> insumos;


    public InsumoAdapter(Context context, List<Insumo> insumos) {
        this.context = context;
        this.insumos = insumos;
    }

    @Override
    public InsumoAdapter.InsumoViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(context).inflate(R.layout.card_teste, viewGroup, false);
        InsumoAdapter.InsumoViewHolder holder = new InsumoAdapter.InsumoViewHolder(view);
        return holder;
    }

    public static class InsumoViewHolder extends RecyclerView.ViewHolder{
        public TextView tNome, tVlrCusto;
        ImageButton btnDelete;
        CardView cardView;
        public InsumoViewHolder(View view){
            super(view);
            tNome = (TextView) view.findViewById(R.id.txtNomeProd);
            tVlrCusto = (TextView) view.findViewById(R.id.txtValorProd);
            btnDelete = (ImageButton) view.findViewById(R.id.imgBtnDel);
            cardView = (CardView) view.findViewById(R.id.cardProduto);
        }
    }

    @Override
    public void onBindViewHolder(final InsumoViewHolder holder, final int position) {
        if(insumos.size() != 0){
            final Insumo p = insumos.get(position);
            holder.tNome.setText(p.getNomeInsumo());
            holder.tVlrCusto.setText(p.getValor().toString());

            holder.cardView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(context, "Clicou no Card para Editar na posição "+position,Toast.LENGTH_SHORT).show();
                    Bundle bundle = new Bundle();
                    //bundle.putString("nome", p.getNomeInsumo());
                    //bundle.putDouble("valor", p.getValor());
                    bundle.putInt("position", position);
                    Intent intent = new Intent(context, UpdateActivity.class);
                    intent.putExtras(bundle);
                    context.startActivity(intent);
                    //update(p, position);
                }
            });

            holder.btnDelete.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(context, "Clicou no Card para Excluir na posição "+position,Toast.LENGTH_SHORT).show();
                    delete(position);
                }
            });
        }
    }

    @Override
    public int getItemCount() {
        return this.insumos != null ? this.insumos.size() : 0;
    }


    private void excluirInsumo(Context context, final int i){
        String titulo = "Excluir";
        String msg = "Deseja excluir este item?";
        AlertDialog alertDialog = new AlertDialog.Builder(context).create();
        alertDialog.setTitle(titulo);
        alertDialog.setMessage(msg);
        alertDialog.setButton(AlertDialog.BUTTON_POSITIVE, "Sim",
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        //deleta("Pproduto",produtos.get(i).get_id());
                        AddActivity addActivity = new AddActivity();
                        //addActivity.deleta(i);

                        dialog.dismiss();
                    }
                });
        alertDialog.setButton(AlertDialog.BUTTON_NEGATIVE, "Não",
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                });
        alertDialog.show();
    }

    private void delete(int position){
        insumos.remove(position);
        notifyItemRemoved(position);
    }

    public void update(Insumo insumo, int position){
        insumos.set(position, insumo);
        //notifyItemChanged(position);
        notifyDataSetChanged();
    }

    public void insere(Insumo insumo){
        insumos.add(insumo);
        notifyDataSetChanged();
    }


这就像不回到 onBindViewHolder 来更新数据。有人可以给我一盏灯吗?如果你需要一些东西,但你找不到任何方法。

编辑-----

添加活动

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

        edtNome = (TextInputEditText) findViewById(R.id.edtNome);
        valorCusto = (TextView) findViewById(R.id.txtValorCustoAdd);
        valorVenda = (TextView) findViewById(R.id.txtValorVendaAdd);
        valorPerc = (TextView) findViewById(R.id.txtValorPercAdd);
        addItem = (FloatingActionButton) findViewById(R.id.fltBtnAddItem);
        addFoto = (FloatingActionButton) findViewById(R.id.fltBtnAddFoto);
        salvar = (FloatingActionButton) findViewById(R.id.fltBtnSalvar);
        imgFoto = (ImageView) findViewById(R.id.imgFoto);
        recyclerView = (RecyclerView) findViewById(R.id.recy);

        edtNome.setTextIsSelectable(true);

        valorCusto.setText(valor.toString());
        valorPerc.setText("0");

        recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setHasFixedSize(true);

        InsumoAdapter insumoAdapter = new InsumoAdapter(getApplicationContext(), insumos);

        recyclerView.setAdapter(insumoAdapter);
        insumoAdapter.notifyDataSetChanged();

        addItem.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(getApplication(), InsertActivity.class);
                startActivity(intent);
            }
        });

        salvar.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Produto produto = new Produto();
                produto.setpNome(edtNome.getText().toString());
                produto.setpValorCusto(somaValor(insumos));
                if(foto == 0){
                    produto.setPfoto(R.drawable.noimage);
                }else{
                    produto.setPfoto(foto);
                }
            }
        });
    }

insumo 的插入活动

update.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                insumo = new Insumo();
                insumo.setNomeInsumo(nome.getText().toString());
                Log.d(TAG, getClass()+" insumo.getNome = "+insumo.getNomeInsumo());
                insumo.setValor(Double.parseDouble(valor.getText().toString()));
                Log.d(TAG, getClass()+" insumo.getValor = "+insumo.getValor());
                AddActivity addActivity = new AddActivity();
                //addActivity.update(insumo, pos);
                InsumoAdapter insumoAdapter = new InsumoAdapter(getBaseContext(), addActivity.lista());
                insumoAdapter.update(insumo, pos);
                insumoAdapter.notifyDataSetChanged();
                finish();
            }
        });

主要活动

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

        recyclerView = (RecyclerView) findViewById(R.id.recyclerTeste);
        FloatingActionButton btn = (FloatingActionButton) findViewById(R.id.fltBtnAdd);

        recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setHasFixedSize(true);

        ProdutoAdapter produtoAdapter = new ProdutoAdapter(getBaseContext(), produtos);

        recyclerView.setAdapter(produtoAdapter);
        produtoAdapter.notifyDataSetChanged();


        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this, AddActivity.class);
                startActivity(intent);
            }
        });

【问题讨论】:

  • 您如何捕获适配器的引用以调用update 方法?您是否通过设置断点来验证您的 update 方法是否被调用?
  • 谢谢@Maddy Blacklisted 是的,我在适配器更新中有日志,它们会执行。我认为它显然没有调用 onBindViewHolder 来更新视图。

标签: android android-recyclerview


【解决方案1】:

问题是;您正在创建一个新的适配器实例,而不是使用附加到您的recyclerView 的适配器。请使用附加到您的 recyclerView 的相同适配器实例。

在您的 recyclerView 实例化的 Activity 中,使用成员引用来包含您的引用。即mInsumoAdapter

然后,当您创建第一个适配器实例并将其附加到您的 recyclerView 时,将其分配给 mInsumoAdapter

最后使用相同的引用来调用你的update 方法。

mInsumoAdapter.update(insumo, pos);

为了在活动和服务之间共享引用,您可以像这样创建一个公共共享类:

public class ReferenceUtil {
    private static InsumoAdapter insumoAdapter;

    public static InsumoAdapter getMainAdapter(){
        return insumoAdapter;
    }

    public static void setMainAdapter(InsumoAdapter adapter) {
        insumoAdapter = adapter;
    }
}

然后在您单击 FAB 时使用 ReferenceUtil.setMainAdapter(adapter);,并在您的下一个活动中使用 ReferenceUtil.getMainAdapter(); 获取您附加的参考并更新该参考以供您的 recyclerView 在运行时更新。

当您返回之前的活动时,请记住将 ReferenceUtil 中的静态 insumoAdapter 设置为 null,因为这可能会导致您的应用程序发生内存泄漏。

【讨论】:

  • 谢谢@Maddy BlackListed 对不起,我不明白……我是安卓新手,所以我有这些基本的疑问。在我的例子中,我调用了一个新的活动,所以我调用了适配器的一个新实例。我这样做错了吗?请记住,添加新项目只有在我尝试更改不更改其视图的记录时才有效,但如果您再次调用编辑它,它已经搜索了更改的项目。
  • 是的,你做错了。适配器仅在附加到视图(在您的情况下为 recyclerView)时才调用 onBindViewHolder,现在至关重要的是仅通知该适配器以使更改反映在您的视图上,而不是另一个实例上。此外,您正在做的另一个上下文错误是,您正在创建一个活动对象,这违反了 Android 应用程序的生命周期。只有当您通过创建和调度意图来请求操作系统时,活动才会由 android 操作系统实例化。
  • 以及您所做的更改,例如添加或更新,它们是在某种程度上常见的支持数据上完成的,而不是在适配器上。由于您的列表正在更新,您将在下一个操作中看到更改,但您的视图不会更新,因为通知了未绑定到视图的错误适配器。
  • 我在有 recyclerView 的同一个活动中有一个 FloatActionButton,在它的 onclick 中我调用包含布局的活动来插入项目数据。保存时,我调用适配器传递布局活动的上下文和我在回收器活动中通过参数获取的列表。我无法将适配器传递给插入活动,因为它有 nullpointerException
  • 您可以有一个类用于在包含静态适配器引用的组件之间共享引用。因此,当您单击您的 FAB 时,您可以将其设置在该类引用中,然后在需要的下一个活动中使用它。我将更新我的答案以添加我刚刚解释的支持代码。
【解决方案2】:

不用创建新的适配器,只需使用当前的适配器实例并将其用于更新和 notifyDataSetChanged。

public InsumoAdapter insumoAdapter;

// Inside onCreate
@Override
protected void onCreate(Bundle savedInstanceState) {
    ....
    insumoAdapter = new InsumoAdapter(getApplicationContext(), insumos);
    ....
}

// Inside Update onClick
update.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
    ....
    insumoAdapter.update(insumo, pos)
    insumoAdapter.notifyDataSetChanged()
}

【讨论】:

  • 谢谢@Aman Arora,但继续但未解决,与插入的更改相同
【解决方案3】:

尝试在您将列表传递给适配器的活动中使用 notifyDataSetChnaged() ,或者您可以在更新它之后执行此操作。像这样的,

RecyclerView.setAdapter(this,list);
notifyDataSetChanged();

InsumoAdapter.update(list,pos);
notifyDataSetChanged();

您可以尝试将这种方式用于所有 CRUD 操作。

【讨论】:

  • 感谢@Nitin Tej,我插入了 notifyDataSetChanged() 但它还没有工作
  • 也可以发布 mainAcivity 吗?
  • 插入帖子感谢@Niltin Tej
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多