Почему RecyclerView.OnScrollListener не является интерфейсом, а абстрактным классом?

Чтобы реализовать шаблон бесконечной прокрутки в RecyclerView, я хочу создать класс, например

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

Поскольку EndlessScrollAdapter должен отвечать за обработку данных и прокрутку, это наиболее удобный способ его реализации.

Но, поскольку в recyclerview-v7-21.0.3, OnScrollListener объявлен как этот

/**
 * 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 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){}
}

Я не могу сделать EndlessScrollAdapter реализовать OnScrollListener.

Итак, как гласит название, есть ли веская причина для OnScrollListener быть классом, а не интерфейсом? Потому что я думаю, что это должен быть интерфейс.

Ответ 1

У меня был тот же вопрос, и он определенно был спроектирован, как ответил в этом отчете об ошибке:

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

Абстрактные классы позволяют фреймворкам добавлять новые методы без нарушения существующих реализаций.

Также введенный diff можно найти здесь:

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

Это изменение добавляет RecyclerView в качестве первого параметра к связанным с прокруткой обратным вызовам.

Он также обнаруживает ошибку, в которой был вызван обратный вызов прокрутки w/намеченный прокрутка вместо реальной суммы прокрутки.

Я также изменил его как абстрактный класс вместо интерфейса, чтобы сделать будущее изменения легче.

Не уверен, что я согласен с изменением, лично, но там я пойду.

Ответ 2

Я не могу заставить EndlessScrollAdapter реализовать OnScrollListener.

Это правда, но вы можете иметь выделенный класс extends RecyclerView.OnScrollListener (конкретный экземпляр RecyclerView.OnScrollListener). Например

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

и то, что вам нужно, просто

mRecyclerView.addOnScrollListener(new MySCrollListener());

Ответ 3

идея избежать установки слушателя в вашем metdod

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

и создать внутренний класс слушателя

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