Why RecyclerView.OnScrollListener is not an interf

2019-04-18 11:10发布

问题:

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.

回答1:

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.



回答2:

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


回答3:

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


回答4:

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