18

To implement Endless Scroll pattern in to the RecyclerView I want to create a class like

public class EndlessScrollAdapter<VH extends ViewHolder> 
        extends RecyclerView.Adapter<VH> implements RecyclerView.OnScrollListener {
}

Because EndlessScrollAdapter should be responsible for both of the data and scroll event handling, this is the most convenient way to implement it.

But, because in recyclerview-v7-21.0.3, OnScrollListener declared like this

/**
 * An OnScrollListener can be set on a RecyclerView to receive messages
 * when a scrolling event has occurred on that RecyclerView.
 *
 * @see RecyclerView#setOnScrollListener(OnScrollListener)
 */
abstract static public class OnScrollListener {
    /**
     * Callback method to be invoked when RecyclerView's scroll state changes.
     *
     * @param recyclerView The RecyclerView whose scroll state has changed.
     * @param newState     The updated scroll state. One of {@link #SCROLL_STATE_IDLE},
     *                     {@link #SCROLL_STATE_DRAGGING} or {@link #SCROLL_STATE_SETTLING}.
     */
    public void onScrollStateChanged(RecyclerView recyclerView, int newState){}

    /**
     * Callback method to be invoked when the RecyclerView has been scrolled. This will be
     * called after the scroll has completed.
     *
     * @param recyclerView The RecyclerView which scrolled.
     * @param dx The amount of horizontal scroll.
     * @param dy The amount of vertical scroll.
     */
    public void onScrolled(RecyclerView recyclerView, int dx, int dy){}
}

I can't make EndlessScrollAdapter implement OnScrollListener.

So as the title says, is there any good reason for OnScrollListener to be a class rather than an interface? Because I think it should be an interface.

Marcus
  • 6,441
  • 10
  • 42
  • 82
Onur
  • 5,492
  • 3
  • 21
  • 31

4 Answers4

14

I had the same question, and it's definitely as designed, as answered in this bug report:

https://code.google.com/p/android/issues/detail?id=79283

Abstract classes allow frameworks to add new methods without breaking existing implementations.

Also the diff that introduced it can be found here:

https://android.googlesource.com/platform/frameworks/support/+/cef7b49%5E!/

This change adds RecyclerView as a first parameter to the scroll related callbacks.

It also fxies a bug where scroll callback was being called w/ the intended scroll amount instead of the real scroll amount.

I also changed it to be an abstract class instead of an interface to make future changes easier.

Not sure I agree with the change, personally, but there ya go.

Kevin Coppock
  • 128,402
  • 43
  • 252
  • 270
  • The reason mentioned on the commit is "I also changed it to be an abstract class instead of an interface to make future changes easier." But one should not make changes based on the future LIKE THIS, because in this case, this class will never change and it could certainly be an interface for the rest of it's life. It's been two years and it's still the same. – LeonardoSibela Dec 20 '16 at 02:21
6

I can't make EndlessScrollAdapter implement OnScrollListener.

It's true, but you can have a dedicated class that extends RecyclerView.OnScrollListener ( a concrete instance of RecyclerView.OnScrollListener). E.g

private class MyScrollListener extends RecyclerView.OnScrollListener {
   // abstract methods implemenations
}

and the what you need is just

mRecyclerView.addOnScrollListener(new MySCrollListener());
Sakiboy
  • 6,255
  • 6
  • 47
  • 63
Blackbelt
  • 148,780
  • 26
  • 271
  • 285
1
 yourRecyclerview.setOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
        }

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
        }
    });
Lalit kumar
  • 1,779
  • 1
  • 15
  • 15
1

the idea to avoid to set the listener in your metdod

...
recyclerView.addOnScrollListener(new ScrollListener());
...

and create an inner listener class

private class ScrollListener extends RecyclerView.OnScrollListener {
    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState){
        // your code there
    }

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        // your code there
    }
}
JulienGenoud
  • 546
  • 8
  • 21
  • Though calling the 'setOnscrollListener' directly on an instance of recycler view is deprecated, going about it this way works like a charm. Thanks! – Vick Swift Aug 10 '16 at 15:57