CustomView 的 ListView 到 RecyclerView 迁移
ListView to RecyclerView Migration for CustomView
我发现我的项目需要从 ListView 转移到 RecyclerView。我遇到了一些设计问题。
在我当前的 ListView 实现中,我使用 CustomView 而不是在那里膨胀。这是我当前的 getView()
public View getView(int position, View containerRow, ViewGroup parent) {
CustomView customView;
if (containerRow == null) customView = new CustomView(mContext);
else customView = (CustomView) containerRow;
DataModel dataModel = getModelForPosition(position);
if (dataModel != null) {
customView.showView(singleDcyde,position);
}
return customView;
}
此处 showView 管理填充文本视图、图像自定义 LayoutParams 以及许多其他内容(2000 行)。
现在我正计划转移到 RecylerView,我对我的设计有点困惑。
- 我是否需要在 RecyclerView.ViewHolder class 中重写整个内容,然后在 onBindViewHolder 中绑定它们?
因为我已经为 Listview 编写了大量代码,所以我不想 rewrite/move 将所有内容从 CustomView 返回到 ViewHolder。
保持设计与 RecyclerView 理念同步的最佳方法是什么。
将 ListView 适配器转换为 RecyclerView.Adapter 非常简单 - 我已经为以下两种实现编写了框架:
private static class MyRecyclerViewAdapter extends RecyclerView.Adapter<CustomViewHolder> {
@Override
public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
CustomView view = createNewCustomView();
return new CustomViewHolder(view);
}
private CustomView createNewCustomView() {
// whatever you need to do to create - I would suggest create from XML rather new'ing up directly
return null;
}
@Override
public void onBindViewHolder(CustomViewHolder holder, int position) {
// bind the data
DataModel dataModel = getModelForPosition(position);
holder.getCustomView().showView(dataModel, position);
}
private DataModel getModelForPosition(int position) {
// TODO: however you did getModelForPosition(int)
return null;
}
@Override
public int getItemCount() {
// TODO: same as getCount()
return 0;
}
}
private static class CustomViewHolder extends RecyclerView.ViewHolder {
public CustomViewHolder(CustomView itemView) {
super(itemView);
}
CustomView getCustomView() {
return ((CustomView) itemView);
}
}
private static class MyListViewAdapter extends BaseAdapter {
@Override
public int getCount() {
// TODO: return correct list size
return 0;
}
@Override
public DataModel getItem(int position) {
// TODO: however you did getModelForPosition(int)
return null;
}
@Override
public long getItemId(int position) {
// however you do
return 0;
}
@Override
public View getView(int position, View containerRow, ViewGroup parent) {
CustomView customView = ((CustomView) containerRow);
if (customView == null) {
customView = createNewCustomView();
}
// could just use getItem(int) here
DataModel dataModel = getModelForPosition(position);
// would it ever be null? if so, you'll have a blank list item
if (dataModel != null) {
customView.showView(dataModel.getSingleDcyde(), position);
}
return customView;
}
private CustomView createNewCustomView() {
// whatever you need to do to create - I would suggest create from XML rather new'ing up directly
return null;
}
private DataModel getModelForPosition(int position) {
return getItem(position);
}
}
private static class DataModel {
Object getSingleDcyde() {
// whatever this is
return null;
}
}
private static class CustomView extends View {
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void showView(Object singleDcyde, int position) {
// bind
}
}
What is the best way to keep design in sync with RecyclerView philosophy.
RecyclerView 背后的理念是关注点分离; RecyclerView 仅负责管理视图回收,LayoutManager 将决定如何测量和定位视图,ViewHolder 试图强制使用 ViewHolder 模式(一种避免多次不必要地调用 findViewById()
的方法),以及 RecyclerView.Adapter 是连接数据的粘合剂。
您现在被迫使用 ViewHolder class。这个想法是每个膨胀布局 (whether or not this call is slow enough to bother doing is debated) 只执行一次所有 findViewById()
调用,例如:
private static final class CustomViewHolder extends RecyclerView.ViewHolder {
private final TextView titleTextView;
private final ImageView avatarImageView;
public CustomViewHolder newInstance(CustomView itemView) {
return new CustomViewHolder(
itemView,
((TextView) itemView.findViewById(R.id.title_text_view)),
((ImageView) itemView.findViewById(R.id.avatar_image_view))
);
}
private CustomViewHolder(CustomView itemView, TextView titleTextView, ImageView avatarImageView) {
super(itemView);
this.titleTextView = titleTextView;
this.avatarImageView = avatarImageView;
}
public void setTitle(String title) {
titleTextView.setText(title);
}
public void setAvatar(Drawable avatar) {
avatarImageView.setImageDrawable(avatar);
}
}
实际上,由于您使用的是自定义视图,很可能(我希望)您已经通过使用 HolderView pattern 避免了对 findViewById(int)
的多次调用。在这种情况下,您可以通过将其视为必要的邪恶来反抗强制使用 ViewHolder 的暴政:
private static final class CustomViewHolder extends RecyclerView.ViewHolder {
public CustomViewHolder(CustomView itemView) {
super(itemView);
}
}
...
...
@Override
public void onBindViewHolder(CustomViewHolder holder, int position) {
Foo foo = getFoo(position);
((CustomView) holder.itemView).myCustomBindMethod(foo);
}
我发现我的项目需要从 ListView 转移到 RecyclerView。我遇到了一些设计问题。
在我当前的 ListView 实现中,我使用 CustomView 而不是在那里膨胀。这是我当前的 getView()
public View getView(int position, View containerRow, ViewGroup parent) {
CustomView customView;
if (containerRow == null) customView = new CustomView(mContext);
else customView = (CustomView) containerRow;
DataModel dataModel = getModelForPosition(position);
if (dataModel != null) {
customView.showView(singleDcyde,position);
}
return customView;
}
此处 showView 管理填充文本视图、图像自定义 LayoutParams 以及许多其他内容(2000 行)。
现在我正计划转移到 RecylerView,我对我的设计有点困惑。 - 我是否需要在 RecyclerView.ViewHolder class 中重写整个内容,然后在 onBindViewHolder 中绑定它们?
因为我已经为 Listview 编写了大量代码,所以我不想 rewrite/move 将所有内容从 CustomView 返回到 ViewHolder。
保持设计与 RecyclerView 理念同步的最佳方法是什么。
将 ListView 适配器转换为 RecyclerView.Adapter 非常简单 - 我已经为以下两种实现编写了框架:
private static class MyRecyclerViewAdapter extends RecyclerView.Adapter<CustomViewHolder> {
@Override
public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
CustomView view = createNewCustomView();
return new CustomViewHolder(view);
}
private CustomView createNewCustomView() {
// whatever you need to do to create - I would suggest create from XML rather new'ing up directly
return null;
}
@Override
public void onBindViewHolder(CustomViewHolder holder, int position) {
// bind the data
DataModel dataModel = getModelForPosition(position);
holder.getCustomView().showView(dataModel, position);
}
private DataModel getModelForPosition(int position) {
// TODO: however you did getModelForPosition(int)
return null;
}
@Override
public int getItemCount() {
// TODO: same as getCount()
return 0;
}
}
private static class CustomViewHolder extends RecyclerView.ViewHolder {
public CustomViewHolder(CustomView itemView) {
super(itemView);
}
CustomView getCustomView() {
return ((CustomView) itemView);
}
}
private static class MyListViewAdapter extends BaseAdapter {
@Override
public int getCount() {
// TODO: return correct list size
return 0;
}
@Override
public DataModel getItem(int position) {
// TODO: however you did getModelForPosition(int)
return null;
}
@Override
public long getItemId(int position) {
// however you do
return 0;
}
@Override
public View getView(int position, View containerRow, ViewGroup parent) {
CustomView customView = ((CustomView) containerRow);
if (customView == null) {
customView = createNewCustomView();
}
// could just use getItem(int) here
DataModel dataModel = getModelForPosition(position);
// would it ever be null? if so, you'll have a blank list item
if (dataModel != null) {
customView.showView(dataModel.getSingleDcyde(), position);
}
return customView;
}
private CustomView createNewCustomView() {
// whatever you need to do to create - I would suggest create from XML rather new'ing up directly
return null;
}
private DataModel getModelForPosition(int position) {
return getItem(position);
}
}
private static class DataModel {
Object getSingleDcyde() {
// whatever this is
return null;
}
}
private static class CustomView extends View {
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void showView(Object singleDcyde, int position) {
// bind
}
}
What is the best way to keep design in sync with RecyclerView philosophy.
RecyclerView 背后的理念是关注点分离; RecyclerView 仅负责管理视图回收,LayoutManager 将决定如何测量和定位视图,ViewHolder 试图强制使用 ViewHolder 模式(一种避免多次不必要地调用 findViewById()
的方法),以及 RecyclerView.Adapter 是连接数据的粘合剂。
您现在被迫使用 ViewHolder class。这个想法是每个膨胀布局 (whether or not this call is slow enough to bother doing is debated) 只执行一次所有 findViewById()
调用,例如:
private static final class CustomViewHolder extends RecyclerView.ViewHolder {
private final TextView titleTextView;
private final ImageView avatarImageView;
public CustomViewHolder newInstance(CustomView itemView) {
return new CustomViewHolder(
itemView,
((TextView) itemView.findViewById(R.id.title_text_view)),
((ImageView) itemView.findViewById(R.id.avatar_image_view))
);
}
private CustomViewHolder(CustomView itemView, TextView titleTextView, ImageView avatarImageView) {
super(itemView);
this.titleTextView = titleTextView;
this.avatarImageView = avatarImageView;
}
public void setTitle(String title) {
titleTextView.setText(title);
}
public void setAvatar(Drawable avatar) {
avatarImageView.setImageDrawable(avatar);
}
}
实际上,由于您使用的是自定义视图,很可能(我希望)您已经通过使用 HolderView pattern 避免了对 findViewById(int)
的多次调用。在这种情况下,您可以通过将其视为必要的邪恶来反抗强制使用 ViewHolder 的暴政:
private static final class CustomViewHolder extends RecyclerView.ViewHolder {
public CustomViewHolder(CustomView itemView) {
super(itemView);
}
}
...
...
@Override
public void onBindViewHolder(CustomViewHolder holder, int position) {
Foo foo = getFoo(position);
((CustomView) holder.itemView).myCustomBindMethod(foo);
}