Search code examples
androidlistviewandroid-ion

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());
    }

Solution

  • 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