无尽的滚动ListView

时间:2014-02-21 21:11:34

标签: android android-listview

我正在使用从在线服务获取的数据填充ListView,该服务以页面形式提供数据。我没有提供“下一页”按钮,而是在用户滚动到页面底部附近时尝试自动加载下一页数据。

使用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());

    }
}

适配器:

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

here开始,我尝试过这个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) {
    }
}

我尝试尽可能地简化代码而不删除任何有用的代码,但我知道它仍然需要一段时间阅读。

在片段的onCreateView中,我调用new RecentTracksTask().execute(1);,它成功地将前15个项目加载到ListView中。在ListView底部附近滚动时,整个内容将替换为第二页,视图将返回到列表顶部。重复此操作只会将我移到列表顶部,仍显示第二页。

  • 如何才能将第n页的项目插入列表底部,而不是替换列表?
  • 如何阻止它将视图移动到列表顶部?

提前致谢!

1 个答案:

答案 0 :(得分:5)

首先,摆脱EndlessScrollListener。然后,更新AsyncTask以获取数据,将其附加到已在使用的适配器,并通知适配器数据集更改。最后,在适配器中,添加一个检查,如果到达列表末尾并请求下一页。但是,我应该警告您,如果您在加载时将最后一个视图滚动到位,您将需要跟踪异步任务并防止重新创建它。

的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) {
        ListView listView = (ListView) getActivity().findViewById(R.id.listview);
        ArrayAdapter adapter = (ArrayAdapter) listView.getAdapter();
        if(adapter == null) {
            adapter = new TracksAdapter(getActivity(), recentTracks);
            listView.setAdapter(adapter);
        } else {
            adapter.addAll(recentTracks);
            adapter.notifyDataSetChanged();
        }
    }
}

适配器:

class TracksAdapter extends ArrayAdapter<Track> {
    private final Context context;
    private final ArrayList<Track> tracks;
    private int currentPage = 0;

    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

        //Check if we're at the end of the list
        if(position == getCount() - 1) {
            currentPage++;
            new RecentTracksTask().execute(currentPage);
        }

        return convertView;
    }
}