abstract class AdapterView extends ViewGroup: 注释已经将其定位解释的很好了:
An AdapterView is a view whose children are determined by an link Adapter.
AdapterView的家族还是挺庞大的, 除了Android自带的ListView/GridView/Spinner/…..这些,很多著名的自定义控件也是基于AdapterView的.ITEM_VIEW_TYPE_IGNORE = -1:这个type的作用是Adapter**不想某个Item的View被recycle的话**,其getItemViewType()就会返回这个值.
ITEM_VIEW_TYPE_HEADER_OR_FOOTER = -2: 对应的View是header/footerView时, getItemViewType()会返回这个值
mInLayout: 标示AdapterView是被layout过了.
mDataChanged: 用来标示AdapterView所bind的data,自上次layout至今是否又产生过变化. mOldItemCount则用来标示data change前adapter中item的数量.
mEmptyView: 就是setEmptyView时的emptyView,注意, emptyView本身并不在AdapterView中.
mBlockLayoutRequests: 当开启这个flag时, 任何对requestLayout()的调用都不会向上传递到父类的View架构中, 这个flag在 一次layout pass的过程中,layout children的时候会被用到.
OnItemClickListener:用的很普遍了, onItemClick(……, View view, int position, long id), 这个回调一般position和id是相等的,不过就像之前说Adapter时,这个完全是自由的,由AdapterView的实现来定制的.
performItemClick(View view, int position, long id),和View的performClick一个道理,等于是模拟一次对ItemView的点击. 如果set了mOnItemClickListener,返回true,否则false.
addView(…)/removeView(….)/这些函数在AdapterView是禁止使用的, 其实现就是直接抛异常: UnsupportedOperationException.这与AdapterView的设计理念有关,因为AdapterView的childView都是由Adapter提供给的,不能有除了Adapter之外的手段来修改childView.
onLayout(…): mLayoutHeight = getHeight(),AdapterView只做了很简单的事情,具体的child layout交予子类来自由实现.
getPositionForView(View view),取得view在Adapter的Dataset中的posititon, 注意view必须是可见的view(不可见的View当前其实没有被在AdapterView中,也就无从查询), 还有一点这里的view可以是ItemView的child, 在实现中可以看到,会先一路向上取到包裹该view的ItemView(当然了,如果本身就是ItemView就不会变了),然后getChildAt(i)挨个做equals匹配(其实应该直接地址匹配就可以). 找不到的话,返回INVALID_POSITION(-1).
getFirstVisiblePosition()/getLastVisiblePosition():返回第一个/最后一个可见的ItemView在DataSet中的position: mFirstPosition/mFirstPosition + getChildCount() - 1,按照AdapterView的设计,第一个可见的ItemView应该就是AdapterView的第一个ChildView,最后一个可见的View就是最后一个childView.
setEmptyView: 同时也是一个RemoteView支持的方法, 在set时就会做一次check,如果adapter==null||adapter.isEmpty(),就会将emptyView显现(updateEmptyStatus).
updateEmptyStatus(empty):紧接上边,会先做一个isInFilterMode(),如果是在filterMode,那么是不会显示emptyView的(相反,会将AdapterView->VISIBLE && emptyView->GONE),否则, 如果emptyView设置了并且有效,那么就会将AdapterView->GONE&&emptyView->VISIBLE,从这个逻辑就可以看到emptyView的使用局限了,其实emptyView就是AdapterView外的一个独立View, 两者的关系仅仅是在empty的时候,AdapterView->GONE&&emptyView->VISIBLE,一个case:如果emptyView本身在布局上不能覆盖AdapterView的位置的话,那么emptyView此时起不到emptyView的效果,最直接的说,emptyView其实就是把我们常用的用view遮挡另一个view方法固化到了AdapterView中((这也是用GONE原因,避免在在LinearLayout这种case,INVISIBLE会造成空白)),没什么复杂的
isInFilterMode():返回false, filter一般在用户在keyboard上输入时可以考虑开启(就是随着根据输入自动过滤AdapterView呈现的itemView).
setFocusable(boolean focusable)/setFocusableInTouchMode(boolean focusable): 从实现上看,只有在!empty或者在filterMode下,才能真正的设置为focusable
getItemAtPosition(int position)/getItemIdAtPosition(int position):很简单,都直接调用的是adapter的相应方法,这也是应该的,因为这个功能完全是依赖于Adapter,当然了,你想在这AdapterView这层玩花样也没人管.
setOnClickListener(OnClickListener l):因为有setOnItemClickListener,所以这个方法是被禁止的.
AdapterDataSetObserver extends DataSetObserver:AdapterView本身没有使用,子类使用,两个callback:
- onChanged: data发生变化,
- mDataChanged=true;
- mOldItemCount = mItemCount;
- mItemCount = getAdapter().getCount();
- 一个对cursor case的特殊处理
- checkFocus()&&requestLayout(),这样才会刷新UI
- onInvalidated: data无效化(注意和change的区别,change可以是从N变为0,但是变为0和data无效化是不一样的case),
- mDataChanged = true;
- 一个对cursor case的特殊处理
- mOldItemCount/mItemCount/mSelectedPosition等内部标示变量全部INVALID或者置0.
- checkFocus()&&requestLayout(),这样才会刷新UI
- AdapterDataSetObserver内部还有一个Parcelable mInstanceState,会在上面两个函数中涉及到AdapterView的onRestoreInstanceState(mInstanceState)/onSaveInstanceState(). clearSavedState()会将mInstanceState null.
- onChanged: data发生变化,
canAnimate(): super.canAnimate() && mItemCount > 0.
AdapterView的selection不部分先不详述.
Android Adapter机制 源码笔记(4): AdapterView
最新推荐文章于 2024-05-27 00:15:00 发布