/* * Copyright (C) 2016 Haruki Hasegawa * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.h6ah4i.android.widget.advrecyclerview.adapter; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; import java.lang.ref.WeakReference; /** * This class behaves like a "proxy" which bridges * {@link RecyclerView.AdapterDataObserver} events to another subscriber object. */ public class BridgeAdapterDataObserver extends RecyclerView.AdapterDataObserver { /** * The subscriber interface. */ public interface Subscriber { /** * Routed {@link RecyclerView.AdapterDataObserver#onChanged()} event. * * @param source The source adapter * @param tag The tag object * @see {@link RecyclerView.AdapterDataObserver#onChanged()} */ void onBridgedAdapterChanged(RecyclerView.Adapter source, Object tag); /** * Routed {@link RecyclerView.AdapterDataObserver#onItemRangeChanged(int, int)} event. * * @param source The source adapter * @param tag The tag object * @param positionStart Position of the first item that has changed * @param itemCount Number of items that have changed * @see {@link RecyclerView.AdapterDataObserver#onItemRangeChanged(int, int)} */ void onBridgedAdapterItemRangeChanged(RecyclerView.Adapter source, Object tag, int positionStart, int itemCount); /** * Routed {@link RecyclerView.AdapterDataObserver#onItemRangeChanged(int, int, Object)} event. * * @param source The source adapter * @param tag The tag object * @param positionStart Position of the first item that has changed * @param itemCount Number of items that have changed * @param payload Optional parameter, use null to identify a "full" update * @see {@link RecyclerView.AdapterDataObserver#onItemRangeChanged(int, int, Object)} */ void onBridgedAdapterItemRangeChanged(RecyclerView.Adapter source, Object tag, int positionStart, int itemCount, Object payload); /** * Routed {@link RecyclerView.AdapterDataObserver#onItemRangeInserted(int, int)} event. * * @param source The source adapter * @param tag The tag object * @param positionStart Position of the first item that was inserted * @param itemCount Number of items inserted * @see {@link RecyclerView.AdapterDataObserver#onItemRangeInserted(int, int)} */ void onBridgedAdapterItemRangeInserted(RecyclerView.Adapter source, Object tag, int positionStart, int itemCount); /** * Routed {@link RecyclerView.AdapterDataObserver#onItemRangeRemoved(int, int)} event. * * @param source The source adapter * @param tag The tag object * @param positionStart Previous position of the first item that was removed * @param itemCount Number of items removed from the data set * @see {@link RecyclerView.AdapterDataObserver#onItemRangeRemoved(int, int)}} */ void onBridgedAdapterItemRangeRemoved(RecyclerView.Adapter source, Object tag, int positionStart, int itemCount); /** * Routed {@link RecyclerView.AdapterDataObserver#onItemRangeChanged(int, int, Object)} event. * * @param source The source adapter * @param tag The tag object * @param fromPosition Previous position of the item. * @param toPosition New position of the item. * @param itemCount Number of items moved (NOTE: this parameter is not actually used, always 1.) * @see {@link RecyclerView.AdapterDataObserver#onItemRangeChanged(int, int, Object)} */ void onBridgedAdapterRangeMoved(RecyclerView.Adapter source, Object tag, int fromPosition, int toPosition, int itemCount); } private final WeakReference<Subscriber> mRefSubscriber; private final WeakReference<RecyclerView.Adapter> mRefSourceHolder; private final Object mTag; /** * Constructor. * * @param subscriber The subscriber object * @param sourceAdapter The event source adapter * @param tag The tag object which users can use in any purpose. */ public BridgeAdapterDataObserver(@NonNull Subscriber subscriber, @NonNull RecyclerView.Adapter sourceAdapter, @Nullable Object tag) { mRefSubscriber = new WeakReference<>(subscriber); mRefSourceHolder = new WeakReference<>(sourceAdapter); mTag = tag; } /** * Returns tag object. * * @return The tag object */ public Object getTag() { return mTag; } /** * This method dispatches {@link RecyclerView.AdapterDataObserver#onChanged()} event to underlying subscriber. * {@inheritDoc} */ @Override public void onChanged() { final Subscriber subscriber = mRefSubscriber.get(); final RecyclerView.Adapter source = mRefSourceHolder.get(); if (subscriber != null && source != null) { subscriber.onBridgedAdapterChanged(source, mTag); } } /** * This method dispatches {@link RecyclerView.AdapterDataObserver#onItemRangeChanged(int, int)} event to underlying subscriber. * {@inheritDoc} */ @Override public void onItemRangeChanged(int positionStart, int itemCount) { final Subscriber subscriber = mRefSubscriber.get(); final RecyclerView.Adapter source = mRefSourceHolder.get(); if (subscriber != null && source != null) { subscriber.onBridgedAdapterItemRangeChanged(source, mTag, positionStart, itemCount); } } /** * This method dispatches {@link RecyclerView.AdapterDataObserver#onItemRangeChanged(int, int, Object)} event to underlying subscriber. * {@inheritDoc} */ @Override public void onItemRangeChanged(int positionStart, int itemCount, Object payload) { final Subscriber subscriber = mRefSubscriber.get(); final RecyclerView.Adapter source = mRefSourceHolder.get(); if (subscriber != null && source != null) { subscriber.onBridgedAdapterItemRangeChanged(source, mTag, positionStart, itemCount, payload); } } /** * This method dispatches {@link RecyclerView.AdapterDataObserver#onItemRangeInserted(int, int)} event to underlying subscriber. * {@inheritDoc} */ @Override public void onItemRangeInserted(int positionStart, int itemCount) { final Subscriber subscriber = mRefSubscriber.get(); final RecyclerView.Adapter source = mRefSourceHolder.get(); if (subscriber != null && source != null) { subscriber.onBridgedAdapterItemRangeInserted(source, mTag, positionStart, itemCount); } } /** * This method dispatches {@link RecyclerView.AdapterDataObserver#onItemRangeRemoved(int, int)} event to underlying subscriber. * {@inheritDoc} */ @Override public void onItemRangeRemoved(int positionStart, int itemCount) { final Subscriber subscriber = mRefSubscriber.get(); final RecyclerView.Adapter source = mRefSourceHolder.get(); if (subscriber != null && source != null) { subscriber.onBridgedAdapterItemRangeRemoved(source, mTag, positionStart, itemCount); } } /** * This method dispatches {@link RecyclerView.AdapterDataObserver#onItemRangeMoved(int, int, int)} event to underlying subscriber. * {@inheritDoc} */ @Override public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { final Subscriber subscriber = mRefSubscriber.get(); final RecyclerView.Adapter source = mRefSourceHolder.get(); if (subscriber != null && source != null) { subscriber.onBridgedAdapterRangeMoved(source, mTag, fromPosition, toPosition, itemCount); } } }