Valentin Lorentz
Valentin Lorentz

Reputation: 9753

Duplicated entries in ListView

I get duplicated items in a ListView. Scrolling back and down sometimes changes the item order. I googled and found many threads reporting this bug, but none of them helped me in fixing my issue.

Here is my code:

Activity:

package com.github.progval.SeenDroid;

import java.util.ArrayList;
import java.util.List;

import com.github.progval.SeenDroid.lib.Connection;
import com.github.progval.SeenDroid.lib.Message;
import com.github.progval.SeenDroid.lib.MessageFetcher;
import com.github.progval.SeenDroid.lib.Query.ParserException;

import android.app.Activity;
import android.app.ListActivity;
import android.content.SharedPreferences;
import android.os.Bundle;

public class ShowUserActivity extends ListActivity {
    private Connection connection;

    public ArrayList<Message> listMessages = new ArrayList<Message>();
    public MessageAdapter adapter;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.profile);
        this.connection = new Connection();
        this.setTitle(R.string.homefeed_title);


        this.listMessages = new MessageFetcher(this.connection).fetchUser();
        this.bindUi();
    }

    private void bindUi() {
        this.adapter = new MessageAdapter(this, this.listMessages);
        this.setListAdapter(adapter);

        // TODO Bind buttons
    }
}

MessageAdapter:

package com.github.progval.SeenDroid;

import java.util.ArrayList;
import java.util.List;
import java.util.zip.Inflater;

import com.github.progval.SeenDroid.lib.Message;

import android.content.Context;
import android.text.Layout;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MessageAdapter extends BaseAdapter {
    private Context context;
    private List<Message> items = new ArrayList<Message>();
    private int lastPosition = 0;

    public MessageAdapter(Context context, List<Message> items) {
        super();
        this.context = context;
        this.items = items;
    }

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

        if (null == convertView) {
            LinearLayout view;
            view = (LinearLayout) LinearLayout.inflate(this.context, R.layout.message, null);
            Log.d("SeenDroid", String.format("Get view %d", position));
            TextView title = new TextView(view.getContext());
            title.setText(this.items.get(position).getTitle());
            view.addView(title);
            return view;
        } else {
            return convertView;
        }
    }


    @Override
    public int getCount() {
        return this.items.size();
    }


    @Override
    public Object getItem(int location) {
        return this.items.get(location);
    }


    @Override
    public long getItemId(int arg0) {
        return arg0;
    }


}

By the way, the output is:

D/SeenDroid(30939): Get view 0
D/SeenDroid(30939): Get view 1
D/SeenDroid(30939): Get view 2
D/SeenDroid(30939): Get view 3
D/SeenDroid(30939): Get view 4
D/SeenDroid(30939): Get view 5
D/SeenDroid(30939): Get view 6
D/SeenDroid(30939): Get view 7
D/SeenDroid(30939): Get view 8
D/SeenDroid(30939): Get view 0
D/SeenDroid(30939): Get view 16

Regards, ProgVal

Upvotes: 18

Views: 31993

Answers (5)

Chien_Khmt
Chien_Khmt

Reputation: 257

public View getView(int position, View convertView, ViewGroup parent) {
    LayoutInflater inflater = (LayoutInflater) context
        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View gridView;
    if (convertView == null) {
        gridView = new View(context);
    } else {
        gridView = (View) convertView;
    }
    gridView = inflater.inflate(R.layout.worker_listmain, null);
    // your source code here!!! Run 100%
    // I got this problem also, I found out the way to solve it! 
    // Please use my source code :D SIMPLE is PERFECT :D
    return gridView;
}

Upvotes: 5

Michele
Michele

Reputation: 6131

You should use the ViewHolder paradigma in your ListAdapter

a nice example can be found here: http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/view/List14.html

Upvotes: 0

Vit Khudenko
Vit Khudenko

Reputation: 28418

Try this:

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

    if (null == convertView) {
        LinearLayout view = (LinearLayout) LinearLayout.inflate(this.context, 
            R.layout.message, null);
        Log.d("SeenDroid", String.format("Get view %d", position));
        TextView title = new TextView(view.getContext());
        title.setText(this.items.get(position).getTitle());
        view.addView(title);
        return view;
    } else {
        LinearLayout view = (LinearLayout) convertView;
        TextView title = (TextView) view.getChildAt(0);
        title.setText(this.items.get(position).getTitle());
        return convertView;
    }
}

Explanation: you got the duplicates because lists on Android reuse UI objects. You are expected to reuse convertView rather than create a new one if it is not null. Of course, you are responsible to set an appropriate value to the instance being reused. Otherwise the value is left from the last "usage".

Upvotes: 34

AlexR
AlexR

Reputation: 115328

ListView does not guarantee uniqueness of items you are added there. It is your responsibility. You are using ArrayList to store items and it can store as many duplicate items as you want.

If you want to removed duplicates put your items into set and then into list again:

listMessages = new ArrayList<Messages>(new LinkedHashSet<Message>(listMessages))

The LinkedHashSet will remove duplicates preserving the initial order of items, ArrayList will allow access elements by position.

Upvotes: 2

user994886
user994886

Reputation: 444

A suggestion - add a log statement after title.setText and write the value obtained from getTitle(). You might get to know why you are getting duplicate entries.

Upvotes: 0

Related Questions