【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() {}

具体用法有时间探讨。我要继续往下走。

 

 

 

posted @ 2013-01-24 13:49  大脚印  阅读(1349)  评论(0编辑  收藏  举报