package cn.mutils.app.ui.adapter; import android.view.ViewGroup; import android.widget.AdapterView; import java.util.LinkedList; import java.util.List; /** * Cache Adapter who provide ability of {@link AdapterView} to general view * * @see AdapterView * @see ItemAdapter */ @SuppressWarnings("unused") public abstract class CacheAdapter<DATA_ITEM, CACHE_ITEM> extends ItemAdapter<DATA_ITEM> { /** * Cache views */ protected List<CACHE_ITEM> mCacheViews; protected boolean mCacheInvalidate; /** * Auto allocate more views */ protected boolean mAutoAllocMore; public CacheAdapter() { super(); mCacheViews = new LinkedList<CACHE_ITEM>(); mAutoAllocMore = true; } @Override public void setDataProvider(List<DATA_ITEM> dataProvider) { mCacheInvalidate = true; super.setDataProvider(dataProvider); } public void setContainer(ViewGroup container) { if (mContainer != null) { if (mContainer.equals(container)) { return; } mContainer.removeAllViews(); } this.mContainer = container; onDataSetChanged(); } /** * Get required cache size for data provider */ protected int getCacheSizeRequired() { if (mDataProvider == null) { return 0; } return mDataProvider.size(); } /** * Get allocate more size for cache */ protected int getCacheSizeMore() { return 1; } /** * Used to know is need to free no use cache */ protected boolean freeCacheNoUse() { return Math.random() > 0.7; } /** * Used to know is need to allocate more cache */ protected boolean allocCacheMore() { return false; } /** * Free cache at index of mCacheViews */ protected abstract void freeCacheAt(int index); /** * Allocate cache at index of mCacheViews */ protected abstract void allocCacheAt(int index); /** * Fix container child views when data provider changed or other things * happen */ protected abstract void fixContainerSize(); /** * Used to get cached IItemView to hold index of data provider */ protected abstract IItemView<DATA_ITEM> getItemViewAt(int index); @Override public void notifyDataSetChanged() { super.notifyDataSetChanged(); this.onDataSetChanged(); } public boolean isAutoAllocMore() { return mAutoAllocMore; } public void setAutoAllocMore(boolean autoAllocMore) { mAutoAllocMore = autoAllocMore; } protected void onDataSetChanged() { if (mContainer == null) { return; } if (mDataProvider == null) { return; } if (mCacheInvalidate) { int requiredViews = getCacheSizeRequired(); if (requiredViews != 0) { if (requiredViews < mCacheViews.size()) { fixContainerSize(); if (freeCacheNoUse()) { for (int i = mCacheViews.size() - 1, startIndex = mCacheViews.size() - requiredViews; i >= startIndex; i--) { freeCacheAt(i); } } } else if (requiredViews > mCacheViews.size()) { for (int i = mCacheViews.size(); i < requiredViews; i++) { allocCacheAt(i); } if (mAutoAllocMore) { if (allocCacheMore()) { for (int i = mCacheViews.size(), size = mCacheViews.size() + getCacheSizeMore(); i < size; i++) { allocCacheAt(i); } } } fixContainerSize(); } else { fixContainerSize(); } } else { fixContainerSize(); } mCacheInvalidate = false; } for (int i = 0, size = mDataProvider.size(); i < size; i++) { IItemView<DATA_ITEM> itemView = getItemViewAt(i); itemView.setPosition(i); itemView.setDataProvider(mDataProvider.get(i)); itemView.onResume(); } } }