2

I am trying to do a endless listview with the Commonsware Endless Adapter (https://github.com/commonsguy/cwac-endless), which works fine by default.

What I am trying to do is a basic chat application. New items should appear at the end and the chat history should be loadable by the endless adapter when the user scrolls to the top.

This by itself is not hard to do. If the ArrayAdapter contains the data s.t. newest items are at position 0, then simply using android:stackFromBottom in the XML declaration of the ListView will put the beginning of the list at the end.

To make sure that the 'load more' inicator is located at the top, I override getItem, getView etc. to provide it with the reversed positions (count-1-position).

My Problem: When the EndlessAdapter adds new data at the end of the List, the "load more" indicator remains visible, causing it to endlessly fetch more data until there is no more to fetch. Expected is that it loads one batch and the user then needs to scroll down (here:up) to load further elements.

What am I missing?

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
Patrick
  • 4,720
  • 4
  • 41
  • 71

2 Answers2

1

Personally, I'd consider pull-to-refresh for this scenario, rather than EndlessAdapter.

That being said, if you are seeing additional rows appear, but the pending view is still there, then your modified getView() is not working properly. The additional rows appearing would indicated that notifyDataSetChanged() itself is functioning (otherwise, those rows would not show up). So, if the pending view is still shown, then getView() presumably is returning the pending view (position 0, I'd guess). In fact, I have no idea how you can get a reverse EndlessAdapter to work, as the first row should always be the pending view and should always be loading data, until you run out of data (and, in the case of a chat, that's possibly never the case).

Hence, again, I'd use pull-to-refresh, or you are going to have to switch to a different "endless" scheme that is paying attention to scroll events, rather than just waiting for the pending view to be displayed, as the trigger to fetch more data.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • Thanks for your answer. I'll try out the "pull to refresh" pattern ( with a different label of course ;) ). I had also tried "smooothScrolls" after loading to move the pending view out of the visible range, but this approach was also unsuccessful. – Patrick Apr 06 '13 at 15:20
0

Do not care on notifyDataSetChanged() help. I implemented an adapter to return Integer.MAX_VALUE as count of elements and especially calculate index in a cache.

Here is some snippet:

    <ListView
        android:id="@+id/logContainer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:stackFromBottom="true" />

......

    logContainer.setOnScrollListener(new OnScrollListener() {
        @Override
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

            if ((logAdapter.getCachedCount() - (Integer.MAX_VALUE - firstVisibleItem)) <= LINES_TO_TRIGGER_PRELOAD && !logAdapter.isPreloading()) {
                logAdapter.preloadAtBackground();
            }
        }

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {}
    });



class LogAdapter extends BaseAdapter {

    private ArrayList<String> logList = new ArrayList<String>();

    @Override
    public int getCount() {
        return Integer.MAX_VALUE;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        TextView logLineView = new TextView(LogViewDialog.this);
        int idx = logList.size() - (Integer.MAX_VALUE - position);
        logLineView.setText(logList.get(idx));
        return logLineView;
    }

    .........
Alexey
  • 146
  • 1
  • 4