Java 更新View.OnClick中的RecyclerView的最佳实践是什么?
不确定解决这个问题的最佳方法。我有一个Java 更新View.OnClick中的RecyclerView的最佳实践是什么?,java,android,Java,Android,不确定解决这个问题的最佳方法。我有一个RecyclerView,它表示数据库中的记录列表(我使用的是SugarOrm;但是,这与问题无关) 我希望表示数据更改,并允许用户通过onClick和onLongClick事件执行CRUD功能。例如,如果用户长按了RecyclerView中的视图,我希望他们可以选择删除记录。问题在于,仅使用视图持有者,更新很容易反映在视图中;但是,删除记录并不是那么容易。ViewHolder作为一个静态内部类,无权访问RecyclerView本身来修改适配器数据或通知数据
RecyclerView
,它表示数据库中的记录列表(我使用的是SugarOrm;但是,这与问题无关)
我希望表示数据更改,并允许用户通过onClick
和onLongClick
事件执行CRUD功能。例如,如果用户长按了RecyclerView
中的视图,我希望他们可以选择删除记录。问题在于,仅使用视图持有者
,更新很容易反映在视图中;但是,删除记录并不是那么容易。ViewHolder
作为一个静态内部类,无权访问RecyclerView
本身来修改适配器数据或通知数据已更改
一个选项是,我可以使内部的ViewHolder
类不是静态的;但是,我应该担心潜在的内存泄漏吗?感觉这将是最简单的解决方案;但是,我是否应该使用完全不同的模式(例如让另一个类成为onClickListener
)
我希望尽可能保持代码可读性和标准实践;但是,如果它将违反最佳实践或变得效率低下,就不会这样做
请参见下面的说明
要在ViewHolder中显示的SugarOrm模型类:
public class SomeModel extends SugarRecord{
@Column(name="Name")
public String name;
@Column(name="AddedDate")
public Date addedDate = new Date();
}
public class SomeModelRecyclerViewAdapter
extends RecyclerView.Adapter<SomeModelRecyclerViewAdapter.ViewHolder>{
private List<SomeModel> data;
public SomeModelRecyclerViewAdapter(List<SomeModel> data) {
this.data = data;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.model_item, parent, false);
ViewHolder holder = new ViewHolder(view);
view.setOnClickListener(holder);
view.setOnLongClickListener(holder);
return holder;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.someModel = data.get(position);
holder.bindData();
}
@Override
public int getItemCount() {
return data.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener, View.OnLongClickListener {
private static final SimpleDateFormat dateFormat =
new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
SomeModel someModel;
TextView modelNameLabel;
TextView modelDateLabel;
public SomeModel getSomeModel() {
return someModel;
}
public void setSomeModel(SomeModel someModel) {
this.someModel = someModel;
}
public ViewHolder(View itemView) {
super(itemView);
}
public void bindData() {
modelNameLabel = (TextView) itemView.findViewById(R.id.modelNameLabel);
modelDateLabel = (TextView) itemView.findViewById(R.id.modelDateLabel);
modelNameLabel.setText(someModel.name);
modelDateLabel.setText(dateFormat.format(someModel.addedDate));
}
@Override
public void onClick(View v) {
someModel.addedDate = new Date();
someModel.save();
bindData();
}
@Override
public boolean onLongClick(View v) {
someModel.delete();
return true;
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.aaronmbond.recyclerviewdilemaexample.MainActivity">
<EditText
android:id="@+id/modelName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
/>
<Button
android:id="@+id/addModelButton"
android:layout_alignParentStart="true"
android:layout_below="@id/modelName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/addModelButtonText"
/>
<android.support.v7.widget.RecyclerView
android:id="@+id/modelList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/addModelButton"
android:layout_alignParentStart="true"
/>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/modelNameLabel"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/modelDateLabel"
android:layout_alignParentStart="true"
android:layout_below="@id/modelNameLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</RelativeLayout>
RecycleServiceAdapter和ViewHolder:
public class SomeModel extends SugarRecord{
@Column(name="Name")
public String name;
@Column(name="AddedDate")
public Date addedDate = new Date();
}
public class SomeModelRecyclerViewAdapter
extends RecyclerView.Adapter<SomeModelRecyclerViewAdapter.ViewHolder>{
private List<SomeModel> data;
public SomeModelRecyclerViewAdapter(List<SomeModel> data) {
this.data = data;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.model_item, parent, false);
ViewHolder holder = new ViewHolder(view);
view.setOnClickListener(holder);
view.setOnLongClickListener(holder);
return holder;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.someModel = data.get(position);
holder.bindData();
}
@Override
public int getItemCount() {
return data.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener, View.OnLongClickListener {
private static final SimpleDateFormat dateFormat =
new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
SomeModel someModel;
TextView modelNameLabel;
TextView modelDateLabel;
public SomeModel getSomeModel() {
return someModel;
}
public void setSomeModel(SomeModel someModel) {
this.someModel = someModel;
}
public ViewHolder(View itemView) {
super(itemView);
}
public void bindData() {
modelNameLabel = (TextView) itemView.findViewById(R.id.modelNameLabel);
modelDateLabel = (TextView) itemView.findViewById(R.id.modelDateLabel);
modelNameLabel.setText(someModel.name);
modelDateLabel.setText(dateFormat.format(someModel.addedDate));
}
@Override
public void onClick(View v) {
someModel.addedDate = new Date();
someModel.save();
bindData();
}
@Override
public boolean onLongClick(View v) {
someModel.delete();
return true;
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.aaronmbond.recyclerviewdilemaexample.MainActivity">
<EditText
android:id="@+id/modelName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
/>
<Button
android:id="@+id/addModelButton"
android:layout_alignParentStart="true"
android:layout_below="@id/modelName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/addModelButtonText"
/>
<android.support.v7.widget.RecyclerView
android:id="@+id/modelList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/addModelButton"
android:layout_alignParentStart="true"
/>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/modelNameLabel"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/modelDateLabel"
android:layout_alignParentStart="true"
android:layout_below="@id/modelNameLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</RelativeLayout>
回收视图项目布局(model\u Item.xml
):
public class SomeModel extends SugarRecord{
@Column(name="Name")
public String name;
@Column(name="AddedDate")
public Date addedDate = new Date();
}
public class SomeModelRecyclerViewAdapter
extends RecyclerView.Adapter<SomeModelRecyclerViewAdapter.ViewHolder>{
private List<SomeModel> data;
public SomeModelRecyclerViewAdapter(List<SomeModel> data) {
this.data = data;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.model_item, parent, false);
ViewHolder holder = new ViewHolder(view);
view.setOnClickListener(holder);
view.setOnLongClickListener(holder);
return holder;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.someModel = data.get(position);
holder.bindData();
}
@Override
public int getItemCount() {
return data.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener, View.OnLongClickListener {
private static final SimpleDateFormat dateFormat =
new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
SomeModel someModel;
TextView modelNameLabel;
TextView modelDateLabel;
public SomeModel getSomeModel() {
return someModel;
}
public void setSomeModel(SomeModel someModel) {
this.someModel = someModel;
}
public ViewHolder(View itemView) {
super(itemView);
}
public void bindData() {
modelNameLabel = (TextView) itemView.findViewById(R.id.modelNameLabel);
modelDateLabel = (TextView) itemView.findViewById(R.id.modelDateLabel);
modelNameLabel.setText(someModel.name);
modelDateLabel.setText(dateFormat.format(someModel.addedDate));
}
@Override
public void onClick(View v) {
someModel.addedDate = new Date();
someModel.save();
bindData();
}
@Override
public boolean onLongClick(View v) {
someModel.delete();
return true;
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.aaronmbond.recyclerviewdilemaexample.MainActivity">
<EditText
android:id="@+id/modelName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
/>
<Button
android:id="@+id/addModelButton"
android:layout_alignParentStart="true"
android:layout_below="@id/modelName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/addModelButtonText"
/>
<android.support.v7.widget.RecyclerView
android:id="@+id/modelList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/addModelButton"
android:layout_alignParentStart="true"
/>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/modelNameLabel"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/modelDateLabel"
android:layout_alignParentStart="true"
android:layout_below="@id/modelNameLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</RelativeLayout>
几天前,我遇到了类似的要求。您对部件的看法是正确的-
ViewHolder作为一个静态内部类,无权访问RecyclerView本身来修改适配器数据或通知数据已更改。
因此,处理这个问题的方法是定义一个接口,该接口封装了viewholder中的所有操作,它需要在RecyclerView上触发某些操作。我的代码中的示例接口定义-
/**
* Parent fragment or activity to implement this interface to listen to item deletes.
* Item deletes effect the state of the parent
*/
public interface OnItemModifiedListener {
void itemDeleted(Cart.CartItem item);
void itemQuantityChanged(Cart.CartItem item, int newQuantity);
void itemRemovedAll();
}
父片段或活动实现此接口,并将其作为其构造函数的一部分传递给适配器。再次使用我的代码中的示例构造函数-
public SimpleItemRecyclerViewAdapter(Context context, List<Cart.CartItem> items, OnItemModifiedListener l) {
//this variable is declared as a adapter state variable
mItemModifiedListener = l;
}
下面的链接也是一个很好的阅读-
希望这有助于……谢谢!此解决方案在保持轻量级的同时工作得很好!