Reputation: 1622
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
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
Upvotes: 1
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