[UPDATE] Weird problem with GridView OnScrollListener and list navigation listener

It turns out that the problem was much simpler than I had originally thought.

The Problem

It was actually two fold. The scroll listener for some reason fires the change event as soon as the gridview’s adapter is set even when there are no items in it. My scroll listener was something like this:

private AbsListView.OnScrollListener mOnScrollListener = new AbsListView.OnScrollListener({
  @Override
  public void onScrollStateChanged (AbsListView view, int scrollState) {}

  @Override
  public void onScroll (AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
    if ((firstVisibleItem + lastVisibleItem) >= totalItemCount && !mAsyncTasksPending) {
      loadMore();
    }
  }
});

The above code ended up calling the loadMore(); even before the gridview’s adapter was loaded with the first page results from the service. That ended up making two requests wastefully. The second problem is because of how I had declared the loadMore(); method. I use AndroidAnnotations to reduce boilerplate code. I annotated loadMore(); with @Background to execute the service request in a background thread to prevent the UI from locking up. But, I didn’t need to do this since I was already taking care that the service request be executed in a background thread using another library called async-http, which by the way is freaking awesome! My guess is, when I set the method to be executed in a background thread it was holding up the gridview’s listener thread somehow which caused the events to accumulate in the call stack. This would probably explain why when I paused the activity and resumed it, it would function normally and the moment I scrolled it and caused it to call loadMore() it would freeze again and none of the callbacks would fire.

A little more than the solution

First, what I ended up doing was removing the redundant @Background annotation from loadMore();. Then, I realized that my activity was a little bloated. So, I created a fragment and shoved the gridview, and managing its adapter into the fragment. I was then able to keep my activity lean. By doing so, I have also opened up the possibility of introducing additional fragments to handle different views if necessary in the future which makes this all the more easy to manage without bloating my activity.

Next, I updated the gridview’s onScroll callback. It was still being called as soon as the adapter was set in the gridview. Initially, the adapter is empty and I don’t want it to call loadMore(); when the first page results haven’t been filled in the adapter yet. Loading the first page is handled through the list navigation listener since that sets the currently selected item for which I then go and fetch the list of images. So now, this is how my updated OnScrollListener looks.

private AbsListView.OnScrollListener mOnScrollListener = new AbsListView.OnScrollListener({
  @Override
  public void onScrollStateChanged (AbsListView view, int scrollState) {}

  @Override
  public void onScroll (AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
    //only load more if the visibleItemCount is > 0, and the user has reached the last row of visible items
    if (visibleItemCount > 0 && ((firstVisibleItem + lastVisibleItem) >= totalItemCount) && !mAsyncTasksPending) {
      loadMore();
    }
  }
});
About these ads

One thought on “[UPDATE] Weird problem with GridView OnScrollListener and list navigation listener

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s