I am populating a ListView with data fetched from an online service, which provides the data in pages. Rather than providing a 'next page' button, I am attempting to automatically load the next page of data when the user scrolls near the bottom of the page.
Data is fetched using an AsyncTask:
class RecentTracksTask extends AsyncTask<Integer, Void, Void> {
ArrayList<Track> recentTracks;
@Override
protected Void doInBackground(Integer... page) {
try {
// Get a page of 15 tracks
// Simplified - getPage accepts 'page' and 'limit' parameters and returns a Collection<Track>
recentTracks = new ArrayList<Track>(getPage(page[0], 15));
} catch () {}
return null;
}
@Override
protected void onPostExecute(Void result) {
TracksAdapter mTracksAdapter = new TracksAdapter(getActivity(),
recentTracks);
ListView listView = (ListView) getActivity().findViewById(R.id.listview);
listView.setAdapter(mTracksAdapter);
listView.setOnScrollListener(new EndlessScrollListener());
}
}
And the adapter:
class TracksAdapter extends ArrayAdapter<Track> {
private final Context context;
private final ArrayList<Track> tracks;
public TracksAdapter(Context context,
ArrayList<Track> recentTrackArrayList) {
super(context, 0, recentTrackArrayList);
this.context = context;
this.tracks = recentTrackArrayList;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_item,
parent, false);
}
final Track track = tracks.get(position);
final TextView tv = (TextView) convertView
.findViewById(R.id.tv);
// Repeat for other views
tv.setText(track.getName());
// Repeat for other views
return convertView;
}
}
From here, I've tried this EndlessScrollListener:
class EndlessScrollListener implements AbsListView.OnScrollListener {
private int visibleThreshold = 5;
private int currentPage = 0;
private int previousTotal = 0;
private boolean loading = true;
public EndlessScrollListener() {
}
public EndlessScrollListener(int visibleThreshold) {
this.visibleThreshold = visibleThreshold;
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (loading) {
if (totalItemCount > previousTotal) {
loading = false;
previousTotal = totalItemCount;
currentPage++;
}
}
if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
// I load the next page of gigs using a background task,
// but you can call any function here.
new RecentTracksTask().execute(currentPage + 1);
loading = true;
}
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
}
I tried simplifying the code as much as possible without removing anything useful but I know it's still a little long to read through.
In the fragment's onCreateView, I call new RecentTracksTask().execute(1);
which successfully loads the first 15 items into the ListView. When scrolling near the bottom of the ListView, the entire contents are replaced with the second page, and the view is returned to the top of the list. Repeating this just moves me to the top of the list, still displaying the second page.
- How can I get it so that the nth page of items is inserted at the bottom of the list, rather than replacing the list?
- How can I stop it from moving the view to the top of the list?
Thanks in advance!