项目未从 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 个。也许有更好的方法,但这确实解决了问题
我正在使用 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 个。也许有更好的方法,但这确实解决了问题