Hendra Anggrian
Hendra Anggrian

Reputation: 5858

Android ListView added item twice

I'm parsing images and link from a website using JSON and add them to ListView:

    exploresAdapter = new ExploreListAdapter(context, new ArrayList<Explore>());
    listView_Explore.setAdapter(exploresAdapter);

    Document document = Jsoup.connect(Server.EXPLORE_LINK).timeout(10 * 1000).get();

    Elements divs = document.select("div[class=module-img] a[href]");

    for (Element div : divs) {
        try {
            href = div.attr("href");

            Elements a = document.select("a[href=" + href + "] img[src]");
                    src = a.attr("src");

            final Bitmap thumbnail = Global.bitmapFromUrl(src);

            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Explore explore = new Explore();
                    explore.setUrl(href);
                    explore.setThumbnail(thumbnail);

                    exploresAdapter.add(explore);
                 }
            });
         } catch (Exception any) {
         //broken link or images, skip
         }
    }

This is my adapter:

public class ExploreListAdapter extends BaseAdapter {
public interface Callback {
    public void onPageRequested(int page);
}

private LayoutInflater inflater;

private List<Explore> explores;

public ExploreListAdapter(Context ctx, List<Explore> explores) {
    inflater = LayoutInflater.from(ctx);
    this.explores = explores;
}

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

@Override
public Object getItem(int position) {
    return position;
}

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

@Override
public boolean hasStableIds() {
    return true;
}

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    Explore explore = this.explores.get(position);

    if (convertView == null) {
        holder = new ViewHolder();
        convertView = inflater.inflate(R.layout.list_explore, parent, false);

        holder.imageView_ExploreAdapter_Thumbnail = (ImageView) convertView.findViewById(R.id.imageView_ExploreAdapter_Thumbnail);

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

    holder.imageView_ExploreAdapter_Thumbnail.setImageBitmap(explore.getThumbnail());

    return convertView;
}

static class ViewHolder {
    ImageView imageView_ExploreAdapter_Thumbnail;
}

public void add(Explore explore) {
    this.explores.add(explore);
    notifyDataSetChanged();
}

public void clear() {
    this.explores.clear();
    notifyDataSetChanged();
}

public List<Explore> getList() {
    return this.explores;
}
}

Explore object:

public class Explore {

private Bitmap thumbnail;
private String url;

public Explore() {

}

public void setThumbnail(Bitmap thumbnail) {
    this.thumbnail = thumbnail;
}

public void setUrl(String url) {
    this.url = url;
}

public Bitmap getThumbnail() {
    return thumbnail;
}

public String getUrl() {
    return url;
}
}

At this point, the items are added twice. Weirdly when I check the items inside the list, they are all in perfect order with no duplicate. I've spent nearly 2 hours on this, any suggestion will be great.

Upvotes: 1

Views: 1185

Answers (2)

Willis
Willis

Reputation: 5336

Your getItem() method seems suspect - you are only returning the ID, not the actual item. It should be something like:

@Override
public Object getItem(int position)
{
    return explores.get(position);
}

EDIT

I vaguely recall having a similar issue at one point with a custom ListView/Adapter combination, but I can't exactly remember what the solution was. Have you tried adding the new elements to the ArrayList and then updating the Adapter instead of adding the new element directly to the Adapter? Something like the following:

ArrayList<Explore> arrayList = new ArrayList<Explore>();

Then when you want to add a new element...

Explore explore = new Explore();
explore.setUrl(href);
explore.setThumbnail(thumbnail);                
arrayList.add(explore);
exploresAdapter.notifyDataSetChanged();

Also, adding a Constructor to your Explore class would be beneficial:

public Explore (Bitmap thumbnail, String url)
{
    super();
    this.thumbnail = thumbnail;
    this.url = url;
}

Then you could add a new element to your ListView with two simple lines:

arrayList.add(new Explore(thumbnail, href));
exploresAdapter.notifyDataSetChanged();

Upvotes: 1

MDMalik
MDMalik

Reputation: 4001

Try the following
a)

public ExploreListAdapter(Context ctx, List<Explore> explores) {
inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

b)

public View getView(int position, View convertView, ViewGroup parent) {
    View vi = convertView;
    try {
        if (convertView == null) {
            vi = inflater.inflate(R.layout.list_explore, null);
            imageView_ExploreAdapter_Thumbnail = (ImageView) vi.findViewById(R.id.imageView_ExploreAdapter_Thumbnail);

        } else {
            imageView_ExploreAdapter_Thumbnail = (ImageView) vi.findViewById(R.id.imageView_ExploreAdapter_Thumbnail);

        }
 imageView_ExploreAdapter_Thumbnail.setImageBitmap(explore.getThumbnail());



    return vi;
}

c) I have declare imageView_ExploreAdapter_Thumbnail below

private LayoutInflater inflater;
ImageView imageView_ExploreAdapter_Thumbnail;

Upvotes: 0

Related Questions