实现具有多个布局的ViewHolder的示例

时间:2015-05-05 10:39:56

标签: android adapter android-viewholder

我设法在我的适配器中实现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);

然后是一些逻辑,点击事件等。

2 个答案:

答案 0 :(得分:0)

根据我的经验,最好扩展BaseAdapter以生成将视图绑定到ViewHolder的干净方法 - 这就是BaseAdapter我如何在任何地方使用它(我仍在使用listview而不是recyclelerview)

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);



}

就我所见,您的代码看起来很好 - 但是每次“绑定”视图时都会调用findView - 这是不必要的。

使用我的BaseAdapter,你将viewHolder设置为newView()中的convertView,并且已经调用findViewById来引用所有视图。在bindView()中,您只需通过convertView.getTag()获取viewHolder并在视图上设置内容,例如:holder.title.setText(item.getTitle())

答案 1 :(得分:0)

另请考虑使用RecyclerView。它是在5.0中引入的(可在支持库中获得)。 RecyclerView使用视图持有者模式作为其实现的一部分,并允许比ListView更灵活。
您可以在Android Developers

上阅读有关将其用于各种方案的指南