Max
Max

Reputation: 1622

Endless adapter for android ListView

I use Ion library to receive data from server. I have problem, that my code makes get request multiple times, so I have data duplication in my list. My adapter code:

public class ArticleAdapter extends ArrayAdapter<Article> {

Future<List<Article>> loadingOfPrevious;

static class ArticleHolder {
    ImageView articleImage;
    TextView articleCaption;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ArticleHolder holder;
    if (convertView == null) {
        convertView = layoutInflater.inflate(R.layout.list_view_item, null);
        holder = new ArticleHolder();
        holder.articleImage = (ImageView) convertView.findViewById(R.id.articleImage);
        holder.articleCaption  = (TextView) convertView.findViewById(R.id.articleCaption);
        convertView.setTag(holder);
    } else {
        holder = (ArticleHolder) convertView.getTag();
    }
    Article article = getItem(position);

    holder.articleCaption.setText(article.getTitle());

    Ion.with(holder.articleImage)
       .placeholder(R.drawable.placeholder)
       .error(R.drawable.default_article_image)
       //.crossfade(true)
       .load(article.getImageUrl());

    // we're near the end of the list adapter, so load more items
    if (position >= getCount() - 3) {
        loadPrevious(getItem(getCount() - 1).getId());
    }

    return convertView;
}

private void loadPrevious(long id) {
    // don't attempt to load more if a load is already in progress
    if (loadingOfPrevious != null && !loadingOfPrevious.isDone() && !loadingOfPrevious.isCancelled()) {
        return;
    }
    String url = "http://example.com/rest-api/"
    url = url + "?id=" + id;
    url = url + "&count=" + 30;
    // This request loads a URL as JsonArray and invokes
    // a callback on completion.
    final String articleUrl = url;
    loadingOfLatest = Ion.with(getContext())
            .load(articleUrl)
            .as(new TypeToken<List<Article>>() {
            })
            .setCallback(new FutureCallback<List<Article>>() {
                @Override
                public void onCompleted(Exception e, List<Article> result) {
                    // this is called back onto the ui thread, no Activity.runOnUiThread or Handler.post necessary.
                    if (e != null) {
                        Toast.makeText(getContext(), "Error.", Toast.LENGTH_LONG).show();
                        return;
                    }
                    // add the article
                    if (result != null) { 
                        Collections.reverse(result);
                        for (int i = 0; i < result.size(); i++) {
                            add(result.get(i));
                        }
                        notifyDataSetChanged();
                    }
                }
            });
}

}

I think the problem is in this part:

// we're near the end of the list adapter, so load more items
    if (position >= getCount() - 3) {
        loadPrevious(getItem(getCount() - 1).getId());
    }

Upvotes: 1

Views: 485

Answers (2)

Hein Htet Aung
Hein Htet Aung

Reputation: 854

You are right! It's because of this code.

    if (position >= getCount() - 3) {
        loadPrevious(getItem(getCount() - 1).getId());
    }

According to your condition, "loadPrevious()" will be called twice.

"getView()" works to return one view for each time. So for the last two items, your condition is true and then call "loadPrevious()" twice. So change and try like this

if (position >= getCount() - 2) {
    loadPrevious(getItem(getCount() - 1).getId());
}

OR

recheck this code

if (loadingOfPrevious != null && !loadingOfPrevious.isDone() &&     !loadingOfPrevious.isCancelled()) {
    return; 
} 

BTW, I want to suggest to try other ways, like using library, customize listview

Android Endless List

Upvotes: 1

kris larson
kris larson

Reputation: 30985

The way I did this was to use an OnScrollListener on the ListView. When the user scrolls and firstVisibleItem + visibleItemCount is near your list limit, start your server data load.

Once the data load is complete, update your list adapter with the new data and call onNotifyDataSetChanged(). The list will then redisplay with your updated data.

Upvotes: 2

Related Questions