package com.pan.simplepicture.adapter; import java.lang.reflect.Constructor; import java.util.Collection; import java.util.List; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import com.nhaarman.listviewanimations.util.Insertable; import com.nhaarman.listviewanimations.util.Swappable; import com.pan.simplepicture.R; import com.pan.simplepicture.activity.BaseActivity; import com.pan.simplepicture.annotations.NonNull; import com.pan.simplepicture.holder.BaseHolder; import com.pan.simplepicture.manager.ThreadManager; public class BaseListAdapter<T> extends BaseAdapter implements Swappable, Insertable<T> { private BaseActivity mActivity; private List<T> mItems; private Class<? extends BaseHolder<T>> clazz; private boolean mHasMore; private boolean mIsLoading; private boolean mLoadError; private View mLoadingView; private View mErrorView; private View mEmptyView; private OnLoadMoreListener<T> listener; public BaseListAdapter(BaseActivity mActivity, List<T> list, Class<? extends BaseHolder<T>> clazz) { this.mActivity = mActivity; this.mItems = list; mHasMore = canLoadMore(); this.clazz = clazz; } @Override public int getCount() { if (mItems != null) { return mItems.size() + 1; } return 0; } public void setOnLoadMoreListener(OnLoadMoreListener<T> listener) { mHasMore = true; this.listener = listener; } @Override public T getItem(int arg0) { // TODO Auto-generated method stub return mItems.get(arg0); } @Override public long getItemId(int arg0) { // TODO Auto-generated method stub return arg0; } @Override public View getView(int position, View convertView, ViewGroup parent) { final int count = getCount(); if ((position >= count - 1) && mHasMore) { loadMore(); } View view = null; if (getItemViewType(position) != 0) { view = getItemView(position, convertView, parent); } else { view = getMoreView(position, convertView, parent); } return view; } private View getItemView(int position, View view, ViewGroup parent) { BaseHolder<T> holder = null; if (view == null) { try { Constructor<? extends BaseHolder<T>> constructor = clazz .getConstructor(BaseActivity.class, mItems .get(position).getClass()); holder = constructor.newInstance(mActivity, mItems.get(position)); } catch (Exception e) { e.printStackTrace(); } } else { holder = (BaseHolder<T>) view.getTag(); holder.setData(mItems.get(position)); } return holder.getRootView(); } protected View getMoreView(int position, View convertView, ViewGroup parent) { View view; if (mHasMore) { if (mIsLoading && !mLoadError) { if (mLoadingView == null) { mLoadingView = mActivity .inflate(R.layout.list_more_loading); } view = mLoadingView; } else { if (mErrorView == null) { mErrorView = mActivity.inflate(R.layout.list_more_error); } view = mErrorView; } } else { if (mEmptyView == null) { mEmptyView = new View(mActivity); } view = mEmptyView; } return view; } public void loadMore() { if (!mIsLoading && !mLoadError) { mIsLoading = true; } else { return; } Runnable runnable = new Runnable() { @Override public void run() { int startIndex = 0; if (mItems != null) { startIndex = mItems.size(); } List<T> moreDatas = onLoadMore(startIndex); if (moreDatas != null) { mItems.addAll(moreDatas); if (moreDatas.size() < 10) { mHasMore = false; } } else { mLoadError = true; } mActivity.post(new Runnable() { @Override public void run() { notifyDataSetChanged(); mIsLoading = false; } }); } }; ThreadManager.getLongPool().execute(runnable); } protected boolean canLoadMore() { return false; } protected List<T> onLoadMore(int starIndex) { if (listener != null) { return listener.OnLoadMore(starIndex); } return null; } @Override public int getViewTypeCount() { return super.getViewTypeCount() + 1;// 加1是为了最后加载更多的布局 } @Override public int getItemViewType(int position) { if (position == getCount() - 1) { return 0;// 加载更多的布局 } else { return 1;// 普通item的布局 } } public interface OnLoadMoreListener<T> { List<T> OnLoadMore(int starIndex); } /** * Returns the items. */ @NonNull public List<T> getItems() { return mItems; } /** * Appends the specified element to the end of the {@code List}. * * @param object * the object to add. * * @return always true. */ public boolean add(@NonNull final T object) { boolean result = mItems.add(object); notifyDataSetChanged(); return result; } @Override public void add(final int index, @NonNull final T item) { mItems.add(index, item); notifyDataSetChanged(); } /** * Adds the objects in the specified collection to the end of this List. The * objects are added in the order in which they are returned from the * collection's iterator. * * @param collection * the collection of objects. * * @return {@code true} if this {@code List} is modified, {@code false} * otherwise. */ public boolean addAll(@NonNull final Collection<? extends T> collection) { boolean result = mItems.addAll(collection); notifyDataSetChanged(); return result; } public boolean contains(final T object) { return mItems.contains(object); } public void clear() { mItems.clear(); notifyDataSetChanged(); } public boolean remove(@NonNull final Object object) { boolean result = mItems.remove(object); notifyDataSetChanged(); return result; } @NonNull public T remove(final int location) { T result = mItems.remove(location); notifyDataSetChanged(); return result; } @Override public void swapItems(final int positionOne, final int positionTwo) { T firstItem = mItems.set(positionOne, getItem(positionTwo)); notifyDataSetChanged(); mItems.set(positionTwo, firstItem); } public void propagateNotifyDataSetChanged( @NonNull final BaseAdapter slavedAdapter) { mDataSetChangedSlavedAdapter = slavedAdapter; } @Override public void notifyDataSetChanged() { super.notifyDataSetChanged(); if (mDataSetChangedSlavedAdapter != null) { mDataSetChangedSlavedAdapter.notifyDataSetChanged(); } } private BaseAdapter mDataSetChangedSlavedAdapter; }