项目未从 RecyclerView 中正确删除

Items not removed properly from RecyclerView

我正在使用 AppWidgetHostViews 填充 RecyclerView。它们一个接一个地排列,每个旁边都有删除按钮。这就是我设置 RecyclerView 和适配器的方式(event.object 是一个 AppWidgetHostView):

        private List<View> viewList = new ArrayList<>();

        mAdapter = new AppWidgetAdapter(this);
        mRecycler.setLayoutManager(new LinearLayoutManager(getActivity()));
        mRecycler.setItemAnimator(new DefaultItemAnimator());
        mRecycler.setAdapter(mAdapter);
        viewList.add((View) event.eventObject);
        mAdapter.setData(viewList);

这是我的适配器,其中包含 AppWidgetHostViews:

public class AppWidgetAdapter extends RecyclerView.Adapter<AppWidgetAdapter.AppWidgetHolder> {

private List<View> viewList = new ArrayList<>();
private AdapterListener listener;

public AppWidgetAdapter(AdapterListener listener) {
    this.listener = listener;
}

public void setData(List<View> list) {
    viewList.clear();
    viewList.addAll(list);
    notifyDataSetChanged();
}

@Override
public AppWidgetHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.app_widget_layout, parent, false);
    return new AppWidgetHolder(view);
}

@Override
public void onBindViewHolder(final AppWidgetHolder holder, int position) {
    final View view = getItem(position);
    holder.setView(view);
    holder.setNum(String.valueOf(position));

    holder.button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int pos = holder.getAdapterPosition();
            viewList.remove(pos);
            notifyItemRemoved(pos);
            notifyItemRangeRemoved(pos, viewList.size());
            listener.onItemRemoved(pos);
        }
    });
}

private View getItem(int position) {
    return !viewList.isEmpty() ? viewList.get(position) : null;
}

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

class AppWidgetHolder extends RecyclerView.ViewHolder {

    private FrameLayout view;
    private Button button;

    AppWidgetHolder(View itemView) {
        super(itemView);
        view = (FrameLayout) itemView.findViewById(R.id.app_widget);
        button = (Button) itemView.findViewById(R.id.delete);

    }

    private void setView (View view) {
        if(view.getParent() != null) {
            ((ViewGroup)view.getParent()).removeView(view);
        }
        this.view.addView(view);
    }

    private void setNum (String num) {
        this.button.setText(num);
    }

}

}

XML 我的 ViewHolder 看起来像这样:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginBottom="20dp">

<Button
    android:layout_centerInParent="true"
    android:id="@+id/delete"
    android:layout_width="50dp"
    android:layout_alignParentEnd="true"
    android:layout_height="wrap_content"
    android:layout_marginLeft="5dp"
    tools:text="Del" />

<FrameLayout
    android:layout_toStartOf="@id/delete"
    android:layout_centerHorizontal="true"
    android:layout_centerInParent="true"
    android:id="@+id/app_widget"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentStart="true" />

所以在 onBindViewHolder 方法中,我正在设置 onClick 侦听器,它应该在该位置删除 AppWidgetHostView。因此在通知项目已删除后,我正在调用 listener.onItemRemoved(pos),它在片段中的实现看起来像这样:

   @Override
public void onItemRemoved(int position) {
    viewList.remove(position);
    mAdapter.setData(viewList);
} 

因此它再次为适配器设置数据并通知数据集已更改。

但问题是,当我单击删除按钮时,项目没有正确删除。 ViewList 调整大小正常,但项目行为异常,例如,如果我添加 3 个项目并删除第二个项目,它会保留在屏幕上,但第三个项目在它上面(第二个仍然可见),然后,如果我删除第一个项目,它会保留,之前的第二个现在被删除,新的第二个在第一个之上。但是如果我点击每个项目的删除按钮,它会删除所有的视图,但是在那个过程中它们会表现得很奇怪......有什么建议,提示吗?

try only adding follow code in onBindViewHolder:

holder.button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        viewList.remove(position);
        notifyItemRemoved(position);
        //notifyDataSetChanged();
    }
});

删除项目时不必调用 setData(List<View> list)。您打了两次电话 viewList.remove(pos);,第一次是 onBindViewHolder,第二次是 onItemRemoved(int position)

根据@Adithya 和@Stanislav Bondar 的建议,我得出了解决方案:

这是 onBindViewHolder 方法:

  @Override
public void onBindViewHolder(final AppWidgetHolder holder, final int position) {
    final View view = getItem(position);
    holder.setView(view);
    holder.setNum(String.valueOf(position));

    holder.button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            int pos = holder.getAdapterPosition();
            viewList.remove(pos);
            listener.onItemRemoved(pos);
        }
    });
}

并在 onItemRemoved 内:

@Override
public void onItemRemoved(int position) {
    viewList.remove(position);
    mAdapter.notifyItemRemoved(position);
}

我必须在适配器和片段内的那个位置删除项目,因为如果我在片段中有 5 个项目传递给适配器,如果我只在适配器中删除它,一旦我再次传递新项目,它将发送 6 个而不是 5 个。也许有更好的方法,但这确实解决了问题