Mat0
Mat0

Reputation: 1195

Why is same ListView item reused everytime?

I'm trying to create a simple chat/message layout. My problem is with the Adapter. I want to use two different layouts. One for outgoing and one incoming messages. Furthermore I would like to use the ViewHolder approach. But my implementation causes the same layout to be inflated/reused everytime getView runs.

Can anyone please explain to me why this is happening? Do I need to use two viewholders?

The relevant code is shown below

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    int direction = getItemViewType(position);

    ViewHolder holder;

    if (convertView == null) {

        int res = 0;
        int resid = 0;
        holder = new ViewHolder();

        if (direction == DIRECTION_INCOMING) {
            holder = new ViewHolder();
            res = R.layout.message_l_box;
            resid = R.id.left_bubble_text;
        }
        else {
            res = R.layout.message_r_box;
            resid = R.id.right_bubble_text;
        }
        convertView = LayoutInflater.from(mContext).inflate(res, parent, false);

        holder.text = (TextView) convertView.findViewById(resid);

        convertView.setTag(holder);
    }
    else {
        holder = (ViewHolder) convertView.getTag();
    }

    holder.text.setText(getItem(position).first);

    return convertView;
}


// Ensure that find by id is not called every time -> could cause slow scrolling
private class ViewHolder {
    TextView text;
}

Upvotes: 0

Views: 58

Answers (1)

dweebo
dweebo

Reputation: 3272

ListViews reuse Views when possible for performance. That is what the convertView View in your code is for. If Android already had another row that you scrolled away from it can be reused so it will be passed into your getView() method. Your code is not creating a new layout if convertView is not null.

You could do something like this, basically store the current layouts direction in the ViewHolder so you know if you can reuse the layout or have to re-inflate it.

private class ViewHolder {    
    TextView text;
    int direction;
}

 if (convertView == null || ((ViewHolder) convertView.getTag()).direction != direction) {
    // same code you have now to layout a new row
    holder.direction = direction
} else { // we know the existing view has same direction so it has the correct layout already inflated and we can reuse it
    holder = (ViewHolder) convertView.getTag();
}

Upvotes: 1

Related Questions