chucklay
chucklay

Reputation: 137

Android ListFragment scrambles the order of elements that aren't initially rendered

So I'm working on a fairly simplistic SMS app to teach myself Android, and I seem to have run into the same problem described in this thread: ListView in ArrayAdapter order get's mixed up when scrolling

Unfortunately, the answer posted there doesn't seem to be working for me. I've been looking at this for a long time now, and I'm stumped. Note that since this is an SMS app, I'm using two different layouts, depending on who sent the message.

Also, in by debugging, I have found that the messages that I pass in my ArrayList are in the correct order, so that doesn't seem to be the problem. Any help would be amazing.

public class MessageAdapter extends ArrayAdapter {

public MessageAdapter(Context context, ArrayList<CryptoMessage> messages){
    super(context, 0, messages);
}

/**
 * {@inheritDoc}
 *
 * @param position
 * @param convertView
 * @param parent
 */
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    CryptoMessage current = (CryptoMessage) getItem(position);

    if(convertView == null){
        if(current.isSent()){
            //This is message that the user sent. Inflate the view for a sent message.
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.sent_message, parent, false);
        }
        else{
            //Otherwise, this is a message that the user received. Inflate the view for a received message.
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.recieved_message, parent, false);
        }
    }

    if(current.isSent()){
        //The current message is a sent message. Get the resources from the sent view.
        TextView body = (TextView) convertView.findViewById(R.id.sentMessageText);
        TextView date = (TextView) convertView.findViewById(R.id.sentMessageDate);

        //Populate the data.
        if(body != null) {
            body.setText(current.getMessage());
        }
        if(date != null) {
            date.setText(current.getDate());
        }
    }
    else{
        TextView body = (TextView) convertView.findViewById(R.id.recievedMessageText);
        TextView date = (TextView) convertView.findViewById(R.id.recievedTimestampText);

        if(body != null) {
            body.setText(current.getMessage());
        }
        if(date != null) {
            date.setText(current.getDate());
        }
    }

    return convertView;
}
}

Upvotes: 1

Views: 50

Answers (1)

CommonsWare
CommonsWare

Reputation: 1007534

Problem #1: Never use LayoutInflater.from() for creating a UI for an activity or fragment. Always call something more specific, like getLayoutInflater() on the Activity. As it stands, your themes will be ignored.

Problem #2: If you are going to use multiple different layouts for rows, you must override getViewTypeCount() to return the number of layouts (in your case, 2). Also, you must override getItemViewType() to return a value (in your case, 0 or 1), indicating which type of row will be used for the supplied position. In your case, that would be based on isSent().

Problem #3: Get rid of the body != null and date != null. If you do not get your widgets for your rows, you want to crash during development, so you can start determining why you did not get your widgets. In this case, had you left those checks off, you would be crashing with NullPointerExceptions, indicating that you did not find the widgets, and perhaps would have had an easier time finding out what went wrong.

Upvotes: 1

Related Questions