AdapterView - 一天一点源码
前言:
由图可知,ListView继承至AbsListView,AbsListView又继承至AdapterView(还实现了TextWatcher方法,往后再说)。
计划从AdapterView开始对ListView进行理解,了解ListView的实现机制。
1、说明
/**
* An AdapterView is a view whose children are determined by an {@link Adapter}.
*/
public abstract class AdapterView<T extends Adapter> extends ViewGroup {...}
AdapterView是一个带有一个Adapter子类泛型的抽象类,继承自ViewGroup。
2、方法
public AdapterView(Context context) {
this(context, null);
}
public AdapterView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public AdapterView(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public AdapterView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
// If not explicitly specified this view is important for accessibility.
if (getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
}
}
AdapterView的5个构造方法。
public interface OnItemClickListener {
void onItemClick(AdapterView<?> parent, View view, int position, long id);
}
public void setOnItemClickListener(@Nullable OnItemClickListener listener) {
mOnItemClickListener = listener;
}
@Nullable
public final OnItemClickListener getOnItemClickListener() {
return mOnItemClickListener;
}
定义了item点击监听接口,实现点击监听的方法,以及获得Item的当前监听器对象的方法
public boolean performItemClick(View view, int position, long id) {
final boolean result;
if (mOnItemClickListener != null) {
playSoundEffect(SoundEffectConstants.CLICK);
mOnItemClickListener.onItemClick(this, view, position, id);
result = true;
} else {
result = false;
}
if (view != null) {
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
}
return result;
}
如果点击监听被定义,实现点击事务。
boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id);
}
public void setOnItemLongClickListener(OnItemLongClickListener listener) {
if (!isLongClickable()) {
setLongClickable(true);
}
mOnItemLongClickListener = listener;
}
定义长按点击事件的方法
public interface OnItemSelectedListener {
void onItemSelected(AdapterView<?> parent, View view, int position, long id);
void onNothingSelected(AdapterView<?> parent);
}
public void setOnItemSelectedListener(@Nullable OnItemSelectedListener listener) {
mOnItemSelectedListener = listener;
}
@Nullable
public final OnItemSelectedListener getOnItemSelectedListener() {
return mOnItemSelectedListener;
}
定义Item选择监听的接口,Item被选择的监听方法,以及获得当前Item监听器的对象的方法。
@Override
public void setOnClickListener(OnClickListener l) {
throw new RuntimeException("Don't call setOnClickListener for an AdapterView. "
+ "You probably want setOnItemClickListener instead");
}
重写父类方法,设置当前AdapterView的监听。
@Override
public void addView(View child) {
throw new UnsupportedOperationException("addView(View) is not supported in AdapterView");
}
@Override
public void addView(View child, int index) {
throw new UnsupportedOperationException("addView(View, int) is not supported in AdapterView");
}
@Override
public void addView(View child, LayoutParams params) {
throw new UnsupportedOperationException("addView(View, LayoutParams) "
+ "is not supported in AdapterView");
}
@Override
public void addView(View child, int index, LayoutParams params) {
throw new UnsupportedOperationException("addView(View, int, LayoutParams) "
+ "is not supported in AdapterView");
}
addView继承自ViewGroup,不支持调用,调用是抛出异常。
@Override
public CharSequence getAccessibilityClassName() {
return AdapterView.class.getName();
}
返回AdapterView的类名。
public abstract T getAdapter();
返回AdapterView的适配器adapter。
public abstract void setAdapter(T adapter);
设置AdapterView的适配器adapter。
@Override
public void removeView(View child) {
throw new UnsupportedOperationException("removeView(View) is not supported in AdapterView");
}
@Override
public void removeViewAt(int index) {
throw new UnsupportedOperationException("removeViewAt(int) is not supported in AdapterView");
}
@Override
public void removeAllViews() {
throw new UnsupportedOperationException("removeAllViews() is not supported in AdapterView");
}
重写的ViewGroup的remove方法,依次为移除指定视图,移除指定位置的视图,移除所有视图等。不可被调用,调用抛出异常。
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
mLayoutHeight = getHeight();
}
重写的ViewGroup的方法,获得当前高度。
public long getSelectedItemId() {
return mNextSelectedRowId;
}
获得选中子控件的Id。
public abstract View getSelectedView();
获得选中的视图。
public Object getSelectedItem() {
T adapter = getAdapter();
int selection = getSelectedItemPosition();
if (adapter != null && adapter.getCount() > 0 && selection >= 0) {
return adapter.getItem(selection);
} else {
return null;
}
}
获得被选中的Item的对象。
public int getCount() {
return mItemCount;
}
获得Item的数量。
public int getPositionForView(View view) {
View listItem = view;
try {
View v;
while ((v = (View) listItem.getParent()) != null && !v.equals(this)) {
listItem = v;
}
} catch (ClassCastException e) {
// We made it up to the window without find this list view
return INVALID_POSITION;
}
if (listItem != null) {
// Search the children for the list item
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
if (getChildAt(i).equals(listItem)) {
return mFirstPosition + i;
}
}
}
// Child not found!
return INVALID_POSITION;
}
传入一个视图,返回传入视图的位置。
public int getFirstVisiblePosition() {
return mFirstPosition;
}
返回适配器设置的屏幕上可显示第一个Item的位置。
public int getLastVisiblePosition() {
return mFirstPosition + getChildCount() - 1;
}
返回适配器设置的屏幕上可显示的最后一个Item的位置。
public abstract void setSelection(int position);
设置当前选择条目。
public void setEmptyView(View emptyView) {
mEmptyView = emptyView;
// If not explicitly specified this view is important for accessibility.
if (emptyView != null
&& emptyView.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
emptyView.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
}
final T adapter = getAdapter();
final boolean empty = ((adapter == null) || adapter.isEmpty());
updateEmptyStatus(empty);
}
设置空视图。
public View getEmptyView() {
return mEmptyView;
}
获得当前AdapterView的空视图对象。
private void updateEmptyStatus(boolean empty) {
if (isInFilterMode()) {
empty = false;
}
if (empty) {
if (mEmptyView != null) {
mEmptyView.setVisibility(View.VISIBLE);
setVisibility(View.GONE);
} else {
// If the caller just removed our empty view, make sure the list view is visible
setVisibility(View.VISIBLE);
}
// We are now GONE, so pending layouts will not be dispatched.
// Force one here to make sure that the state of the list matches
// the state of the adapter.
if (mDataChanged) {
this.onLayout(false, mLeft, mTop, mRight, mBottom);
}
} else {
if (mEmptyView != null) mEmptyView.setVisibility(View.GONE);
setVisibility(View.VISIBLE);
}
}
设置空视图的可见状态。
public Object getItemAtPosition(int position) {
T adapter = getAdapter();
return (adapter == null || position < 0) ? null : adapter.getItem(position);
}
传入一个Item位置,获得Adapter中Item对应的数据
public long getItemIdAtPosition(int position) {
T adapter = getAdapter();
return (adapter == null || position < 0) ? INVALID_ROW_ID : adapter.getItemId(position);
}
传入Item的位置,获得Adapter中Item对应的位置
class AdapterDataSetObserver extends DataSetObserver {
private Parcelable mInstanceState = null;
@Override
public void onChanged() {
mDataChanged = true;
mOldItemCount = mItemCount;
mItemCount = getAdapter().getCount();
// Detect the case where a cursor that was previously invalidated has
// been repopulated with new data.
if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
&& mOldItemCount == 0 && mItemCount > 0) {
AdapterView.this.onRestoreInstanceState(mInstanceState);
mInstanceState = null;
} else {
rememberSyncState();
}
checkFocus();
requestLayout();
}
@Override
public void onInvalidated() {
mDataChanged = true;
if (AdapterView.this.getAdapter().hasStableIds()) {
// Remember the current state for the case where our hosting activity is being
// stopped and later restarted
mInstanceState = AdapterView.this.onSaveInstanceState();
}
// Data is invalid so we should reset our state
mOldItemCount = mItemCount;
mItemCount = 0;
mSelectedPosition = INVALID_POSITI结结结结结结
N;
mSelectedRowId = INVALID_ROW_ID;
mNextSelectedPosition = INVALID_POSITION;
mNextSelectedRowId = INVALID_ROW_ID;
mNeedSync = false;
checkFocus();
requestLayout();
}
public void clearSavedState() {
mInstanceState = null;
}
}
定义内部类,为AdapterView设置观察者,通过重写的onChange,onInvalidated,clearSavedState,对Adapter的状态及参数进行观察,实时做出相应改变。
总结
以上并不是AdapterView的全部源码,只是将我觉得重要的源码,以及一些在ListView中有体现的源码进行了阅读。
粗略感觉AdapterView已实现了Listview的大部分基础功能。
AdapterView中定义了设置ListView中item监听的各种方法,以及设置Adapter,内部内继承观察者类,对数据进行监控…等等。
一点一点的理解,逐步了解ListView的实现机制。