RecyclerView notifyItemChanged(position)使用notifyDataSetChanged()

时间:2018-02-27 17:28:03

标签: java android android-recyclerview notifydatasetchanged

所以我有一个RecyclerView,在每个xml中我都会有一个复选框,当按下时会从RecyclerView中删除该特定项目。这就是我至少要做的事情。正如我所理解的那样,我需要使用notifyItemChanged(position); (它在底部)。

但是当我使用notifyItemChanged(position)时;如果按下这些顺序中的复选框,它只会删除正确的项目:1,2,3,4,5或5,4,3,2,1。如果我尝试删除第一项,则删除它,但如果我想删除第三项,则删除第四项。

我发现的另一个选项是使用notifyDataSetChanged();并且它以任何顺序工作,但是没有动画显示。

我希望在添加和删除项目时有动画,所以如果有一种方法可以使用notifyDataSetChanged();我想帮忙。

public class ListAdapter extends RecyclerView.Adapter{

SharedPreferences sharedpreferences, prefs;
public static final String MyPREFERENCES = "MyPrefs";
public static final String date = "date";
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.nd_table, parent, false);
    return new ListViewHolder(view);
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int adapterPosition) {
    //((ListViewHolder) holder).bindView(position);
    String data = hwName.get(adapterPosition);
    String data2 = hwDesc.get(adapterPosition);
    ((ListViewHolder) holder).mItemText.setText(data);
    ((ListViewHolder) holder).mItemText2.setText(data2);
    ((ListViewHolder) holder).buttonDelete.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View view){
            removeItem(adapterPosition);
            notifyItemChanged(adapterPosition);
        }
    });
}


@Override
public int getItemCount() {
    return hwName.size();
}

public class ListViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

    private TextView mItemText, mItemText2;
    public CheckBox buttonDelete;

    public ListViewHolder(View itemView) {
        super(itemView);
        mItemText = (TextView) itemView.findViewById(R.id.pam_name);
        mItemText2 = (TextView) itemView.findViewById(R.id.pam_nd);
        buttonDelete = (CheckBox) itemView.findViewById(R.id.nd_checkbox);
        itemView.setOnClickListener(this);
    }

    public void bindView(int position) {
        String value = hwName.get(position);
        String value2 = hwDesc.get(position);

        mItemText.setText(value);
        mItemText2.setText(value2);

        //notifyItemInserted(hwName.size());
    }


    public void onClick(View view) {

    }
}

public void removeItem(int position){
    hwName.remove(position);
    hwDesc.remove(position);
    //notifyDataSetChanged();
    notifyItemRemoved(position);
    notifyItemChanged(position);
}}

崩溃报告:

  

致命的例外:主要       处理:com.sajev.slush,PID:14166       java.lang.IndexOutOfBoundsException:索引:5,大小:5       at java.util.ArrayList.remove(ArrayList.java:477)       at com.sajev.slush.ListAdapter.removeItem(ListAdapter.java:89)       在com.sajev.slush.ListAdapter $ 1.onClick(ListAdapter.java:45)       在android.view.View.performClick(View.java:5646)       在android.widget.CompoundButton.performClick(CompoundButton.java:123)       在android.view.View $ PerformClick.run(View.java:22459)       在android.os.Handler.handleCallback(Handler.java:761)       在android.os.Handler.dispatchMessage(Handler.java:98)       在android.os.Looper.loop(Looper.java:156)       在android.app.ActivityThread.main(ActivityThread.java:6523)       at java.lang.reflect.Method.invoke(Native Method)       在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:941)       在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:831)

1 个答案:

答案 0 :(得分:0)

有两个问题:

致电notifyItemChanged()

后请勿致电notifyItemRemoved()

调用notifyItemRemoved()会告诉适配器以前position处的项目不再存在,而且您只需要这样做。调用notifyItemChanged()告诉适配器position处的项目已被修改(可能是其名称已更改,但没有更改),因此删除项目时无意使用。

你因为按顺序调用这两个而导致崩溃。想象一下,您的列表中只有一个项目,然后将其删除。当您调用notifyItemRemoved()时,适配器现在知道您的列表中包含零项。但是你打电话给notifyItemChanged(),所以适配器试图获得第一个项目......但是列表是空的,所以你崩溃了。

传递给position的{​​{1}}参数不能是onBindViewHolder()

(有关详细信息,请参阅https://www.youtube.com/watch?v=LqBlYJTfLP4 at 43:10。)

编译器无法阻止您将final关键字添加到final的{​​{1}}参数中,但这样做是一个逻辑错误。当您调用positiononBindViewHolder()等方法时,其他视图持有者重新绑定,因此notifyItemRemoved()参数将不再反映现实。

请勿在点击侦听器中使用该notifyItemInserted()参数。相反,在运行时查找它。考虑到这两个问题,这里有一些更新的代码:

position

position