/*
* 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.CallSuper;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.ViewGroup;
import com.h6ah4i.android.widget.advrecyclerview.utils.WrappedAdapterUtils;
import java.util.Collections;
import java.util.List;
/**
* A simple wrapper class. It just bypasses all methods and events to the wrapped adapter.
* Use this class as a default implementation of {@link WrapperAdapter}, so extend it
* and override each methods to build your own specialized adapter!
*/
public class SimpleWrapperAdapter<VH extends RecyclerView.ViewHolder>
extends RecyclerView.Adapter<VH> implements WrapperAdapter<VH>, BridgeAdapterDataObserver.Subscriber {
private static final String TAG = "ARVSimpleWAdapter";
private static final boolean LOCAL_LOGD = false;
private RecyclerView.Adapter<VH> mWrappedAdapter;
private BridgeAdapterDataObserver mBridgeObserver;
protected static final List<Object> FULL_UPDATE_PAYLOADS = Collections.emptyList();
/**
* Constructor
* @param adapter The adapter which to be wrapped
*/
public SimpleWrapperAdapter(@NonNull RecyclerView.Adapter<VH> adapter) {
mWrappedAdapter = adapter;
mBridgeObserver = new BridgeAdapterDataObserver(this, mWrappedAdapter, null);
mWrappedAdapter.registerAdapterDataObserver(mBridgeObserver);
super.setHasStableIds(mWrappedAdapter.hasStableIds());
}
/**
* Returns whether the wrapped adapter exists.
* @return True if underlying adapter is present. Otherwise, false.
*/
public boolean isWrappedAdapterAlive() {
return mWrappedAdapter != null;
}
/**
* Returns underlying adapter.
* @return The underlying adapter instance
*/
public RecyclerView.Adapter<VH> getWrappedAdapter() {
return mWrappedAdapter;
}
/**
* {@inheritDoc}
*/
@Override
public void getWrappedAdapters(@NonNull List<RecyclerView.Adapter> adapters) {
if (mWrappedAdapter != null) {
adapters.add(mWrappedAdapter);
}
}
/**
* {@inheritDoc}
*/
@Override
public void release() {
onRelease();
if (mWrappedAdapter != null && mBridgeObserver != null) {
mWrappedAdapter.unregisterAdapterDataObserver(mBridgeObserver);
}
mWrappedAdapter = null;
mBridgeObserver = null;
}
/**
* {@inheritDoc}
*/
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
if (isWrappedAdapterAlive())
mWrappedAdapter.onAttachedToRecyclerView(recyclerView);
}
/**
* {@inheritDoc}
*/
@Override
public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
if (isWrappedAdapterAlive())
mWrappedAdapter.onDetachedFromRecyclerView(recyclerView);
}
/**
* {@inheritDoc}
*/
@Override
public void onViewAttachedToWindow(VH holder) {
onViewAttachedToWindow(holder, holder.getItemViewType());
}
/**
* {@inheritDoc}
*/
@Override
public void onViewAttachedToWindow(VH holder, int viewType) {
if (isWrappedAdapterAlive()) {
WrappedAdapterUtils.invokeOnViewAttachedToWindow(mWrappedAdapter, holder, viewType);
}
}
/**
* {@inheritDoc}
*/
@Override
public void onViewDetachedFromWindow(VH holder) {
onViewDetachedFromWindow(holder, holder.getItemViewType());
}
/**
* {@inheritDoc}
*/
@Override
public void onViewDetachedFromWindow(VH holder, int viewType) {
if (isWrappedAdapterAlive()) {
WrappedAdapterUtils.invokeOnViewDetachedFromWindow(mWrappedAdapter, holder, viewType);
}
}
/**
* {@inheritDoc}
*/
@Override
public void onViewRecycled(VH holder) {
onViewRecycled(holder, holder.getItemViewType());
}
/**
* {@inheritDoc}
*/
@Override
public void onViewRecycled(VH holder, int viewType) {
if (isWrappedAdapterAlive()) {
WrappedAdapterUtils.invokeOnViewRecycled(mWrappedAdapter, holder, viewType);
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean onFailedToRecycleView(VH holder) {
return onFailedToRecycleView(holder, holder.getItemViewType());
}
/**
* {@inheritDoc}
*/
@Override
public boolean onFailedToRecycleView(VH holder, int viewType) {
boolean shouldBeRecycled = false;
if (isWrappedAdapterAlive()) {
shouldBeRecycled = WrappedAdapterUtils.invokeOnFailedToRecycleView(mWrappedAdapter, holder, viewType);
}
if (shouldBeRecycled) {
return true;
}
return super.onFailedToRecycleView(holder);
}
/**
* {@inheritDoc}
*/
@Override
public void setHasStableIds(boolean hasStableIds) {
super.setHasStableIds(hasStableIds);
if (isWrappedAdapterAlive())
mWrappedAdapter.setHasStableIds(hasStableIds);
}
/**
* {@inheritDoc}
*/
@Override
public VH onCreateViewHolder(ViewGroup parent, int viewType) {
return mWrappedAdapter.onCreateViewHolder(parent, viewType);
}
/**
* {@inheritDoc}
*/
@Override
public void onBindViewHolder(VH holder, int position) {
onBindViewHolder(holder, position, FULL_UPDATE_PAYLOADS);
}
/**
* {@inheritDoc}
*/
@Override
public void onBindViewHolder(VH holder, int position, List<Object> payloads) {
if (isWrappedAdapterAlive())
mWrappedAdapter.onBindViewHolder(holder, position, payloads);
}
/**
* {@inheritDoc}
*/
@Override
public int getItemCount() {
return isWrappedAdapterAlive() ? mWrappedAdapter.getItemCount() : 0;
}
/**
* {@inheritDoc}
*/
@Override
public long getItemId(int position) {
return mWrappedAdapter.getItemId(position);
}
/**
* {@inheritDoc}
*/
@Override
public int getItemViewType(int position) {
return mWrappedAdapter.getItemViewType(position);
}
/**
* {@inheritDoc}
*/
@Override
public void unwrapPosition(@NonNull UnwrapPositionResult dest, int position) {
dest.adapter = getWrappedAdapter();
dest.position = position;
}
/**
* {@inheritDoc}
*/
@Override
public int wrapPosition(@NonNull AdapterPathSegment pathSegment, int position) {
if (pathSegment.adapter == getWrappedAdapter()) {
return position;
} else {
return RecyclerView.NO_POSITION;
}
}
@CallSuper
protected void onRelease() {
// override this method if needed
}
protected void onHandleWrappedAdapterChanged() {
notifyDataSetChanged();
}
protected void onHandleWrappedAdapterItemRangeChanged(int positionStart, int itemCount) {
notifyItemRangeChanged(positionStart, itemCount);
}
protected void onHandleWrappedAdapterItemRangeChanged(int positionStart, int itemCount, Object payload) {
notifyItemRangeChanged(positionStart, itemCount, payload);
}
protected void onHandleWrappedAdapterItemRangeInserted(int positionStart, int itemCount) {
notifyItemRangeInserted(positionStart, itemCount);
}
protected void onHandleWrappedAdapterItemRangeRemoved(int positionStart, int itemCount) {
notifyItemRangeRemoved(positionStart, itemCount);
}
protected void onHandleWrappedAdapterRangeMoved(int fromPosition, int toPosition, int itemCount) {
if (itemCount != 1) {
throw new IllegalStateException("itemCount should be always 1 (actual: " + itemCount + ")");
}
notifyItemMoved(fromPosition, toPosition);
}
@Override
public final void onBridgedAdapterChanged(RecyclerView.Adapter source, Object tag) {
if (LOCAL_LOGD) {
Log.d(TAG, "onBridgedAdapterChanged");
}
onHandleWrappedAdapterChanged();
}
@Override
public final void onBridgedAdapterItemRangeChanged(RecyclerView.Adapter source, Object tag, int positionStart, int itemCount) {
if (LOCAL_LOGD) {
Log.d(TAG, "onBridgedAdapterItemRangeChanged(positionStart = " + positionStart + ", itemCount = " + itemCount + ")");
}
onHandleWrappedAdapterItemRangeChanged(positionStart, itemCount);
}
@Override
public final void onBridgedAdapterItemRangeChanged(RecyclerView.Adapter sourceAdapter, Object tag, int positionStart, int itemCount, Object payload) {
if (LOCAL_LOGD) {
Log.d(TAG, "onBridgedAdapterItemRangeChanged(positionStart = " + positionStart + ", itemCount = " + itemCount + ", payload = " + payload + ")");
}
onHandleWrappedAdapterItemRangeChanged(positionStart, itemCount, payload);
}
@Override
public final void onBridgedAdapterItemRangeInserted(RecyclerView.Adapter sourceAdapter, Object tag, int positionStart, int itemCount) {
if (LOCAL_LOGD) {
Log.d(TAG, "onBridgedAdapterItemRangeInserted(positionStart = " + positionStart + ", itemCount = " + itemCount + ")");
}
onHandleWrappedAdapterItemRangeInserted(positionStart, itemCount);
}
@Override
public final void onBridgedAdapterItemRangeRemoved(RecyclerView.Adapter sourceAdapter, Object tag, int positionStart, int itemCount) {
if (LOCAL_LOGD) {
Log.d(TAG, "onBridgedAdapterItemRangeRemoved(positionStart = " + positionStart + ", itemCount = " + itemCount + ")");
}
onHandleWrappedAdapterItemRangeRemoved(positionStart, itemCount);
}
@Override
public final void onBridgedAdapterRangeMoved(RecyclerView.Adapter sourceAdapter, Object tag, int fromPosition, int toPosition, int itemCount) {
if (LOCAL_LOGD) {
Log.d(TAG, "onBridgedAdapterRangeMoved(fromPosition = " + fromPosition + ", toPosition = " + toPosition + ", itemCount = " + itemCount + ")");
}
onHandleWrappedAdapterRangeMoved(fromPosition, toPosition, itemCount);
}
}