首先,RecyclerView 功能虽然强大但是没有像ListView的addHaderView()或者addFooterView之类的方法,但是我们实际开发中可能需要这么去做,必须我们自己去实现,为了给RecyclerView添加header 或者footer 我们今天来分析ListView是如何实现此功能的。
一、我们直接来看ListView.addHeaderView()方法,重点就是我们的adapter.
public void addHeaderView(View v, Object data, boolean isSelectable) {
//可以看到ListView把我们的HeaderView封装成了对象FixedViewInfo 存在了集合当中
//private ArrayList<FixedViewInfo> mHeaderViewInfos = Lists.newArrayList();
//private ArrayList<FixedViewInfo> mFooterViewInfos = Lists.newArrayList();
//说明可以添加多个headerView 和 footerView
//
final FixedViewInfo info = new FixedViewInfo();
info.view = v;
info.data = data;
info.isSelectable = isSelectable;
mHeaderViewInfos.add(info);
mAreAllItemsSelectable &= isSelectable;
// Wrap the adapter if it wasn't already wrapped.
if (mAdapter != null) {
// 如果设置的adapter不是HeaderViewListAdapter 就创建一个HeaderViewListAdapter 并把mAdapter传进去
// 这里就是说如果 添加有headerView或者footerView 就是用HeaderViewListAdapter来装饰我们的adapter
// 装饰模式
if (!(mAdapter instanceof HeaderViewListAdapter)) {
mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter);
}
// In the case of re-adding a header view, or adding one later on,
// we need to notify the observer.
if (mDataSetObserver != null) {
mDataSetObserver.onChanged();
}
}
}
二、继续来看ListView.setAdapter()方法
@Override
public void setAdapter(ListAdapter adapter) {
if (mAdapter != null && mDataSetObserver != null) {
mAdapter.unregisterDataSetObserver(mDataSetObserver);
}
resetList();
mRecycler.clear();
这里和 addHeaderView方法一样装饰了我们的adapter
if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
} else {
mAdapter = adapter;
}
........................
requestLayout();
}
三、上面我们看到了 HeaderViewListAdapter来装饰我们自己的adapter 我们这里就来看一下 HeaderViewListAdapter
public class HeaderViewListAdapter implements WrapperListAdapter, Filterable {
private final ListAdapter mAdapter;
再看WraperListAdapter:
public interface WrapperListAdapter extends ListAdapter {
/**
* Returns the adapter wrapped by this list adapter.
*
* @return The {@link android.widget.ListAdapter} wrapped by this adapter.
*/
public ListAdapter getWrappedAdapter();
}
可以看到 HeaderViewListAdapter 和我们自己的传进来的Adapter 都实现了ListAdapter接口,
这和我们普通的adapter没有什么大的区别 都拥有常用的方法 比如:getView()、getItem()、getCount()、getItemId()等
继续看getView()方法:
//重点看这里:
public View getView(int position, View convertView, ViewGroup parent) {
// Header (negative positions will throw an IndexOutOfBoundsException)
int numHeaders = getHeadersCount();
if (position < numHeaders) {
return mHeaderViewInfos.get(position).view;
}
// Adapter
final int adjPosition = position - numHeaders;
int adapterCount = 0;
if (mAdapter != null) {
adapterCount = mAdapter.getCount();
// 代理(做一个切面的编程):根据不同的position返回不同的view
if (adjPosition < adapterCount) {
return mAdapter.getView(adjPosition, convertView, parent);
}
}
// Footer (off-limits positions will throw an IndexOutOfBoundsException)
return mFooterViewInfos.get(adjPosition - adapterCount).view;
}
看到这里我想大家都明白了,getCount(),getItem()也是同样如此:
public int getCount() {
if (mAdapter != null) {
return getFootersCount() + getHeadersCount() + mAdapter.getCount();
} else {
return getFootersCount() + getHeadersCount();
}
}
getItemId()方法:
public long getItemId(int position) {
int numHeaders = getHeadersCount();
if (mAdapter != null && position >= numHeaders) {
int adjPosition = position - numHeaders;
int adapterCount = mAdapter.getCount();
if (adjPosition < adapterCount) {
return mAdapter.getItemId(adjPosition);
}
}
return -1;
}
看到这里我们了解了 ListView添加HeaderView 和 FooterView的实现原理,可以为RecyclerView添加简单的HeaderView 或者FooterView了。每天学一点,加油!