【Android】AdapterView源码部分解析(二)
注:AdapterView继承于ViewGroup,所以这里标记为(二)。
同样官方解释:
1 An AdapterView is a view whose children are determined by an {@link Adapter}.
很容易就想到ListView和GridView两个View。类定义如下:
1 public abstract class AdapterView<T extends Adapter> extends ViewGroup
贴一下源码的部分属性,看上去有好多之前不知道的信息:
1 /** 2 * The position of the first child displayed 3 */ 4 @ViewDebug.ExportedProperty 5 int mFirstPosition = 0; 6 7 /** 8 * The offset in pixels from the top of the AdapterView to the top 9 * of the view to select during the next layout. 10 */ 11 int mSpecificTop; 12 13 /** 14 * Position from which to start looking for mSyncRowId 15 */ 16 int mSyncPosition; 17 18 /** 19 * Row id to look for when data has changed 20 */ 21 long mSyncRowId = INVALID_ROW_ID; 22 23 /** 24 * Height of the view when mSyncPosition and mSyncRowId where set 25 */ 26 long mSyncHeight; 27 28 /** 29 * True if we need to sync to mSyncRowId 30 */ 31 boolean mNeedSync = false; 32 33 /** 34 * Indicates whether to sync based on the selection or position. Possible 35 * values are {@link #SYNC_SELECTED_POSITION} or 36 * {@link #SYNC_FIRST_POSITION}. 37 */ 38 int mSyncMode; 39 40 /** 41 * Our height after the last layout 42 */ 43 private int mLayoutHeight; 44 45 /** 46 * Sync based on the selected child 47 */ 48 static final int SYNC_SELECTED_POSITION = 0; 49 50 /** 51 * Sync based on the first child displayed 52 */ 53 static final int SYNC_FIRST_POSITION = 1; 54 55 /** 56 * Maximum amount of time to spend in {@link #findSyncPosition()} 57 */ 58 static final int SYNC_MAX_DURATION_MILLIS = 100; 59 60 /** 61 * Indicates that this view is currently being laid out. 62 */ 63 boolean mInLayout = false; 64 65 /** 66 * The listener that receives notifications when an item is selected. 67 */ 68 OnItemSelectedListener mOnItemSelectedListener; 69 70 /** 71 * The listener that receives notifications when an item is clicked. 72 */ 73 OnItemClickListener mOnItemClickListener; 74 75 /** 76 * The listener that receives notifications when an item is long clicked. 77 */ 78 OnItemLongClickListener mOnItemLongClickListener; 79 80 /** 81 * True if the data has changed since the last layout 82 */ 83 boolean mDataChanged;
比如这个:
1 /** 2 * The offset in pixels from the top of the AdapterView to the top 3 * of the view to select during the next layout. 4 */ 5 int mSpecificTop; 6 7 /** 8 * Position from which to start looking for mSyncRowId 9 */ 10 int mSyncPosition;
还有这个:
1 /** 2 * The listener that receives notifications when an item is selected. 3 */ 4 OnItemSelectedListener mOnItemSelectedListener;
接口定义如下:
1 /** 2 * Interface definition for a callback to be invoked when 3 * an item in this view has been selected. 4 */ 5 public interface OnItemSelectedListener { 6 /** 7 * Callback method to be invoked when an item in this view has been 8 * selected. 9 * 10 * Impelmenters can call getItemAtPosition(position) if they need to access the 11 * data associated with the selected item. 12 * 13 * @param parent The AdapterView where the selection happened 14 * @param view The view within the AdapterView that was clicked 15 * @param position The position of the view in the adapter 16 * @param id The row id of the item that is selected 17 */ 18 void onItemSelected(AdapterView<?> parent, View view, int position, long id); 19 20 /** 21 * Callback method to be invoked when the selection disappears from this 22 * view. The selection can disappear for instance when touch is activated 23 * or when the adapter becomes empty. 24 * 25 * @param parent The AdapterView that now contains no selected item. 26 */ 27 void onNothingSelected(AdapterView<?> parent); 28 }
重载的时候,当方法不支持的时候,可以选择以下方案:直接抛出异常
1 /** 2 * This method is not supported and throws an UnsupportedOperationException when called. 3 * 4 * @param child Ignored. 5 * 6 * @throws UnsupportedOperationException Every time this method is invoked. 7 */ 8 @Override 9 public void addView(View child) { 10 throw new UnsupportedOperationException("addView(View) is not supported in AdapterView"); 11 }
看一个方法:
1 /** 2 * @return The data corresponding to the currently selected item, or 3 * null if there is nothing selected. 4 */ 5 public Object getSelectedItem() { 6 T adapter = getAdapter(); 7 int selection = getSelectedItemPosition(); 8 if (adapter != null && adapter.getCount() > 0 && selection >= 0) { 9 return adapter.getItem(selection); 10 } else { 11 return null; 12 } 13 }
重载Adapter的时候,经常疑惑getItem这个方法是用来干嘛的,这里有解。
还有下面这个有意思的方法:
1 /** 2 * Sets the view to show if the adapter is empty 3 */ 4 public void setEmptyView(View emptyView) { 5 mEmptyView = emptyView; 6 7 final T adapter = getAdapter(); 8 final boolean empty = ((adapter == null) || adapter.isEmpty()); 9 updateEmptyStatus(empty); 10 }
当adapter为空的时候显示什么,而不用自己去判断~
下面这个类乃是数据集监听者,在Adapter里面有一个方法叫做notifyDataSetChanged(),是用来刷新AdapterView的显示数据的,有关么?
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_POSITION; mSelectedRowId = INVALID_ROW_ID; mNextSelectedPosition = INVALID_POSITION; mNextSelectedRowId = INVALID_ROW_ID; mNeedSync = false; checkSelectionChanged(); checkFocus(); requestLayout(); } public void clearSavedState() { mInstanceState = null; } }
源码中有一大段是用来控制数据集变化,这里就不具体贴出来的,检几个:
1 /** 2 * Remember enough information to restore the screen state when the data has 3 * changed. 4 * 5 */ 6 void rememberSyncState() {}
1 /** 2 * Searches the adapter for a position matching mSyncRowId. The search starts at mSyncPosition 3 * and then alternates between moving up and moving down until 1) we find the right position, or 4 * 2) we run out of time, or 3) we have looked at every position 5 * 6 * @return Position of the row that matches mSyncRowId, or {@link #INVALID_POSITION} if it can't 7 * be found 8 */ 9 int findSyncPosition() {}
具体用法有时间探讨。我要继续往下走。