Reputation: 11608
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
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