未从RecyclerView中正确删除的项目

时间:2017-07-11 08:33:55

标签: android android-recyclerview android-viewholder

我用AppWidgetHostViews填充RecyclerView。它们按一个在另一个下面排序,每个都有旁边的删除按钮。这就是我设置RecyclerView和Adapter的方式(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);
    }

}

}

我的ViewHolder的XML看起来像这样:

<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个项目并删除第二个项目,例如,它会停留在屏幕上,但第三个位于其上面(第二个仍然可见),然后,如果我删除第一个项目,它会保留,现在删除了前一个第二个,新的第二个删除了第一个。但是如果我点击每个项目的删除按钮,它将删除所有视图,但是在这个过程中它们会表现得很奇怪...有什么建议吗,提示?

3 个答案:

答案 0 :(得分:3)

  

尝试仅在onBindViewHolder中添加以下代码:

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

答案 1 :(得分:1)

删除项目时,您无需致电setData(List<View> list)。您第一次在viewList.remove(pos);onBindViewHolder

中调用了两次onItemRemoved(int position)

答案 2 :(得分:0)

使用@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 ..也许有更好的方法,但这确实解决了问题