/* * Copyright 2015 "Henry Tao <hi@henrytao.me>" * * 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.stfalcon.frescoimageviewer.adapter; import android.os.Bundle; import android.os.Parcelable; import android.support.v4.view.PagerAdapter; import android.util.SparseArray; import android.view.View; import android.view.ViewGroup; import java.util.ArrayList; import java.util.List; /* * Created by henrytao on 11/13/15. */ public abstract class RecyclingPagerAdapter<VH extends ViewHolder> extends PagerAdapter { public abstract int getItemCount(); public abstract void onBindViewHolder(VH holder, int position); public abstract VH onCreateViewHolder(ViewGroup parent, int viewType); private static final String STATE = RecyclingPagerAdapter.class.getSimpleName(); private static final String TAG = RecyclingPagerAdapter.class.getSimpleName(); public static boolean DEBUG = false; private SparseArray<RecycleCache> mRecycleTypeCaches = new SparseArray<>(); private SparseArray<Parcelable> mSavedStates = new SparseArray<>(); public RecyclingPagerAdapter() { } @Override public void destroyItem(ViewGroup parent, int position, Object object) { if (object instanceof ViewHolder) { ((ViewHolder) object).detach(parent); } } @Override public int getCount() { return getItemCount(); } @Override public int getItemPosition(Object object) { return POSITION_NONE; } @SuppressWarnings("unchecked") @Override public Object instantiateItem(ViewGroup parent, int position) { int viewType = getItemViewType(position); if (mRecycleTypeCaches.get(viewType) == null) { mRecycleTypeCaches.put(viewType, new RecycleCache(this)); } ViewHolder viewHolder = mRecycleTypeCaches.get(viewType).getFreeViewHolder(parent, viewType); viewHolder.attach(parent, position); onBindViewHolder((VH) viewHolder, position); viewHolder.onRestoreInstanceState(mSavedStates.get(getItemId(position))); return viewHolder; } @Override public boolean isViewFromObject(View view, Object object) { return object instanceof ViewHolder && ((ViewHolder) object).itemView == view; } @Override public void notifyDataSetChanged() { super.notifyDataSetChanged(); for (ViewHolder viewHolder : getAttachedViewHolders()) { onNotifyItemChanged(viewHolder); } } @Override public void restoreState(Parcelable state, ClassLoader loader) { if (state instanceof Bundle) { Bundle bundle = (Bundle) state; bundle.setClassLoader(loader); SparseArray<Parcelable> ss = bundle.containsKey(STATE) ? bundle.getSparseParcelableArray(STATE) : null; mSavedStates = ss != null ? ss : new SparseArray<Parcelable>(); } super.restoreState(state, loader); } @Override public Parcelable saveState() { Bundle bundle = new Bundle(); for (ViewHolder viewHolder : getAttachedViewHolders()) { mSavedStates.put(getItemId(viewHolder.mPosition), viewHolder.onSaveInstanceState()); } bundle.putSparseParcelableArray(STATE, mSavedStates); return bundle; } public int getItemId(int position) { return position; } public int getItemViewType(int position) { return 0; } protected void onNotifyItemChanged(ViewHolder viewHolder) { } private List<ViewHolder> getAttachedViewHolders() { List<ViewHolder> attachedViewHolders = new ArrayList<>(); int n = mRecycleTypeCaches.size(); for (int i = 0; i < n; i++) { for (ViewHolder viewHolder : mRecycleTypeCaches.get(mRecycleTypeCaches.keyAt(i)).mCaches) { if (viewHolder.mIsAttached) { attachedViewHolders.add(viewHolder); } } } return attachedViewHolders; } private static class RecycleCache { private final RecyclingPagerAdapter mAdapter; private final List<ViewHolder> mCaches; RecycleCache(RecyclingPagerAdapter adapter) { mAdapter = adapter; mCaches = new ArrayList<>(); } ViewHolder getFreeViewHolder(ViewGroup parent, int viewType) { int i = 0; ViewHolder viewHolder; for (int n = mCaches.size(); i < n; i++) { viewHolder = mCaches.get(i); if (!viewHolder.mIsAttached) { return viewHolder; } } viewHolder = mAdapter.onCreateViewHolder(parent, viewType); mCaches.add(viewHolder); return viewHolder; } } }