多布局ViewHolder实现示例
Example of implementing ViewHolder with multiple layouts
我设法在我的适配器中实现了 ViewHolder,但由于我对此比较陌生,我不确定以下实现是否正确。目前我的数组中有 10 个元素,但我花了大约 3-4 分钟进行调试,我不确定我是否理解 View Holder 的工作流程。我知道这不一定是一个问题,但我想检查一下以防它写得不好。
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
COLOR_GREEN = R.color.ck_in_category_green;
View rowView = convertView;
ViewHolder holder;
int type = getItemViewType(position);
if (convertView == null) {
holder = new ViewHolder();
switch (type) {
case TYPE_MINE_OR_ACCEPTED:
convertView = View.inflate(context, R.layout.item_notif_mine_or_accepted, null);
rowView = handleViewForMineOrAccepted(holder, convertView, checkIns.get(position));
break;
case TYPE_TAGGING:
convertView = View.inflate(context, R.layout.item_notif_tagged_or_invited, null);
rowView = handleViewForTaggingOrInvitation(holder, convertView, checkIns.get(position), true);
break;
case TYPE_INVITATION:
convertView = View.inflate(context, R.layout.item_notif_tagged_or_invited, null);
rowView = handleViewForTaggingOrInvitation(holder, convertView, checkIns.get(position), false);
break;
}
rowView.setTag(holder);
} else {
holder = (ViewHolder) rowView.getTag();
switch (type) {
case TYPE_MINE_OR_ACCEPTED:
rowView = handleViewForMineOrAccepted(holder, convertView, checkIns.get(position));
break;
case TYPE_TAGGING:
rowView = handleViewForTaggingOrInvitation(holder, convertView, checkIns.get(position), true);
break;
case TYPE_INVITATION:
rowView = handleViewForTaggingOrInvitation(holder, convertView, checkIns.get(position), false);
break;
}
}
return rowView;
}
handleView 方法之一:
private View handleViewForMineOrAccepted(final ViewHolder holder, View view, final Checkin checkin) {
holder.checkInPicture = (ImageView) view.findViewById(R.id.mine_or_accepted_check_in_picture);
holder.locationSmall = (TextView) view.findViewById(R.id.check_in_location_small);
holder.locationBig = (TextView) view.findViewById(R.id.check_in_location_big);
holder.creatorFrame = (RelativeLayout) view.findViewById(R.id.check_in_creator_frame);
holder.tagged1Layout = (RelativeLayout) view.findViewById(R.id.notif_check_in_tagged_1);
holder.tagged2Layout = (RelativeLayout) view.findViewById(R.id.notif_check_in_tagged_2);
holder.tagged3Layout = (RelativeLayout) view.findViewById(R.id.notif_check_in_tagged_3);
holder.time = (TextView) view.findViewById(R.id.join_request_check_in_time);
holder.calendar = (ImageView) view.findViewById(R.id.join_request_time_icon);
holder.creator = (ImageView) view.findViewById(R.id.confirmed_friend_1);
holder.tagged1 = (ImageView) view.findViewById(R.id.confirmed_friend_2);
holder.tagged2 = (ImageView) view.findViewById(R.id.confirmed_friend_3);
holder.tagged3 = (ImageView) view.findViewById(R.id.confirmed_friend_4);
holder.tagged1Layout.setVisibility(View.GONE);
holder.tagged2Layout.setVisibility(View.GONE);
holder.tagged3Layout.setVisibility(View.GONE);
后面是一些逻辑,点击事件等
根据我的经验,最好扩展 BaseAdapter 以生成将视图绑定到 ViewHolder 的干净方法 - 这就是我如何在任何地方使用它的 BaseAdapter(我仍在使用 listview 而不是 recyclerview 的地方)
public abstract class MyBaseAdapter extends BaseAdapter {
protected LayoutInflater inflater;
protected Context context;
public TikBaseAdapter(Context context) {
this.context = context;
this.inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public final View getView(int position, View convertView, ViewGroup parent) {
int type = getItemViewType(position);
if (convertView == null) {
convertView = newView(type, parent);
}
bindView(position, type, convertView);
return convertView;
}
/** Create a new instance of a view for the specified {@code type}. */
public abstract View newView(int type, ViewGroup parent);
/** Bind the data for the specified {@code position} to the {@code view}. */
public abstract void bindView(int position, int type, View view);
}
就我所见,你的代码看起来不错 - 但你每次在 "binding" 视图时调用 findView - 这是不必要的。
使用我的 BaseAdapter,您将 viewHolder 设置为 newView() 中的 convertView,并且已经调用 findViewById 来引用所有视图。在 bindView() 中,您只需通过 convertView.getTag() 获取 viewHolder 并在视图上设置内容,例如:holder.title.setText(item.getTitle())
也可以考虑使用 RecyclerView
。它是在 5.0 中引入的(在支持库中可用)。 RecyclerView
使用视图持有者模式作为其实现的一部分,并允许比 ListView
更灵活。
您可以在 Android Developers
上阅读有关在各种情况下使用它的指南
我设法在我的适配器中实现了 ViewHolder,但由于我对此比较陌生,我不确定以下实现是否正确。目前我的数组中有 10 个元素,但我花了大约 3-4 分钟进行调试,我不确定我是否理解 View Holder 的工作流程。我知道这不一定是一个问题,但我想检查一下以防它写得不好。
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
COLOR_GREEN = R.color.ck_in_category_green;
View rowView = convertView;
ViewHolder holder;
int type = getItemViewType(position);
if (convertView == null) {
holder = new ViewHolder();
switch (type) {
case TYPE_MINE_OR_ACCEPTED:
convertView = View.inflate(context, R.layout.item_notif_mine_or_accepted, null);
rowView = handleViewForMineOrAccepted(holder, convertView, checkIns.get(position));
break;
case TYPE_TAGGING:
convertView = View.inflate(context, R.layout.item_notif_tagged_or_invited, null);
rowView = handleViewForTaggingOrInvitation(holder, convertView, checkIns.get(position), true);
break;
case TYPE_INVITATION:
convertView = View.inflate(context, R.layout.item_notif_tagged_or_invited, null);
rowView = handleViewForTaggingOrInvitation(holder, convertView, checkIns.get(position), false);
break;
}
rowView.setTag(holder);
} else {
holder = (ViewHolder) rowView.getTag();
switch (type) {
case TYPE_MINE_OR_ACCEPTED:
rowView = handleViewForMineOrAccepted(holder, convertView, checkIns.get(position));
break;
case TYPE_TAGGING:
rowView = handleViewForTaggingOrInvitation(holder, convertView, checkIns.get(position), true);
break;
case TYPE_INVITATION:
rowView = handleViewForTaggingOrInvitation(holder, convertView, checkIns.get(position), false);
break;
}
}
return rowView;
}
handleView 方法之一:
private View handleViewForMineOrAccepted(final ViewHolder holder, View view, final Checkin checkin) {
holder.checkInPicture = (ImageView) view.findViewById(R.id.mine_or_accepted_check_in_picture);
holder.locationSmall = (TextView) view.findViewById(R.id.check_in_location_small);
holder.locationBig = (TextView) view.findViewById(R.id.check_in_location_big);
holder.creatorFrame = (RelativeLayout) view.findViewById(R.id.check_in_creator_frame);
holder.tagged1Layout = (RelativeLayout) view.findViewById(R.id.notif_check_in_tagged_1);
holder.tagged2Layout = (RelativeLayout) view.findViewById(R.id.notif_check_in_tagged_2);
holder.tagged3Layout = (RelativeLayout) view.findViewById(R.id.notif_check_in_tagged_3);
holder.time = (TextView) view.findViewById(R.id.join_request_check_in_time);
holder.calendar = (ImageView) view.findViewById(R.id.join_request_time_icon);
holder.creator = (ImageView) view.findViewById(R.id.confirmed_friend_1);
holder.tagged1 = (ImageView) view.findViewById(R.id.confirmed_friend_2);
holder.tagged2 = (ImageView) view.findViewById(R.id.confirmed_friend_3);
holder.tagged3 = (ImageView) view.findViewById(R.id.confirmed_friend_4);
holder.tagged1Layout.setVisibility(View.GONE);
holder.tagged2Layout.setVisibility(View.GONE);
holder.tagged3Layout.setVisibility(View.GONE);
后面是一些逻辑,点击事件等
根据我的经验,最好扩展 BaseAdapter 以生成将视图绑定到 ViewHolder 的干净方法 - 这就是我如何在任何地方使用它的 BaseAdapter(我仍在使用 listview 而不是 recyclerview 的地方)
public abstract class MyBaseAdapter extends BaseAdapter {
protected LayoutInflater inflater;
protected Context context;
public TikBaseAdapter(Context context) {
this.context = context;
this.inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public final View getView(int position, View convertView, ViewGroup parent) {
int type = getItemViewType(position);
if (convertView == null) {
convertView = newView(type, parent);
}
bindView(position, type, convertView);
return convertView;
}
/** Create a new instance of a view for the specified {@code type}. */
public abstract View newView(int type, ViewGroup parent);
/** Bind the data for the specified {@code position} to the {@code view}. */
public abstract void bindView(int position, int type, View view);
}
就我所见,你的代码看起来不错 - 但你每次在 "binding" 视图时调用 findView - 这是不必要的。
使用我的 BaseAdapter,您将 viewHolder 设置为 newView() 中的 convertView,并且已经调用 findViewById 来引用所有视图。在 bindView() 中,您只需通过 convertView.getTag() 获取 viewHolder 并在视图上设置内容,例如:holder.title.setText(item.getTitle())
也可以考虑使用 RecyclerView
。它是在 5.0 中引入的(在支持库中可用)。 RecyclerView
使用视图持有者模式作为其实现的一部分,并允许比 ListView
更灵活。
您可以在 Android Developers