Droidman
Droidman

Reputation: 11608

android custom ListView - trying to understand how getView() works

The matter: I'm trying to use a custom ListView to display messages in a chat. I've parametrized the ArrayList with objects of my own class, code goes below.

The problem: message text and timestamp stays always the same each time the layout is inflated, something is wrong in the getView() method but I can't figure out what.

P.S. ChatActivity contains a lot of code, I'll only post the things relevant to the problem to keep it clean.

Message.java:

 public class Message{

/*
 * 1- outgoing
 * 2-incoming
 * */

public String message;
public String timestamp;
public TextView tvmessage, tvtimestamp;
public ImageView indicator;
public int type;

public Message(String text, int type){
    this.timestamp = generateTimestamp();
    this.message = text;
    this.type=type;

    Log.d("Message", message);
    //Message text is set correctly each time the constructor is called

}

@SuppressLint("SimpleDateFormat")
public String generateTimestamp() {
    SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
    String ts = sdf.format(new Date());

    return ts;
}

    }

ChatActivity:

 private ArrayList<Message> OutgoingMessagesList;
 private SingleChatAdapter adapter;
  private EditText etInput;
 lv = getListView();
    adapter = new SingleChatAdapter(this, OutgoingMessagesList);
    lv.setAdapter(adapter);

public void sendMessage() {

    String tmpMessage = etInput.getText().toString().trim();
    /*--- check whether the message string is empty ---*/
    if (tmpMessage.length() > 0) {

        Message msg = new Message(tmpMessage, 1);

        OutgoingMessagesList.add(msg);

        /*
         * TODO: save the message to local database, send the message to
         * server, save it to server database and forward to the recipient
         */
        adapter.notifyDataSetChanged();
        etInput.setText("");

    } else {

        MiscUtils.gibShortToast(this, getString(R.string.msgEmpty));
    }

}

The adapter class where I believe the problem is:

    public final class SingleChatAdapter extends BaseAdapter {
private Context context;
Message msg;
private ArrayList<Message> messages;

public SingleChatAdapter(Context context, ArrayList<Message> chat) {

    this.context = context;
    this.messages = chat;
    Log.d("ChatAdapter", "called constructor");

}

public int getCount() {
    return messages.size();
}

public Object getItem(int position) {
    return messages.get(position);
}

public long getItemId(int position) {
    return position;
}

public View getView(int position, View convertView, ViewGroup viewGroup) {

    msg = (Message) getItem(position);

    if (convertView == null) {

        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        // TODO message_incoming should be inflated for messages received
        // from server
        convertView = (LinearLayout) inflater.inflate(
                R.layout.message_outgoing, null);

        convertView.setTag(msg);

    } else {

        msg = (Message) convertView.getTag();

    }

    msg.tvmessage = (TextView) convertView
            .findViewById(R.id.tvMessageOutgoing);
    msg.tvtimestamp = (TextView) convertView.findViewById(R.id.tvTimestamp);
    msg.indicator = (ImageView) convertView
            .findViewById(R.id.imgMessageState);

    msg.tvmessage.setText(msg.message);

    msg.tvtimestamp.setText(msg.timestamp);

    return convertView;
}

message string from my Message class contains the correct values each time, but the text inflated into the list stays always the same. What am I missing?

Upvotes: 0

Views: 2621

Answers (2)

Michał Z.
Michał Z.

Reputation: 4119

You should delete else statement (the one inside getView) because now it works this way: If convertView is null (first item of listView is created) then it's inflated and you set your message as a tag to this view. But then when next items are created, convertView isn't null anymore and your else statement gets called. So your message is replaced by the one saved as a tag to the convertView.

You should also watch the video mentioned by confucius :)

Upvotes: 3

confucius
confucius

Reputation: 13327

if you want to understand how the ListView works and the getView refer to this talk for Roman Guy also a nice blog post here

Upvotes: 2

Related Questions