Spinner类OnItemSelected回调流程

来源:互联网 发布:windows安装服务 编辑:程序博客网 时间:2024/05/29 14:33

上一篇文章 Spinner类setSelection执行流程源码解析 我们分析了setSelection方法执行的整个流程,那么Spinner(准确来讲是AdapterView)是如何通知我们selection状态已经改变了?
这边文章我们就来趁热打铁来聊聊这个话题。

其实我们都知道,要想知道selection状态是否改变我们只需要调用setOnItemSelectedListener方法注册一个回调方法就可以了。那么这个回调方法究竟在什么时候被回调呢?

还记得 Spinner类setSelection执行流程源码解析 一文layout方法末尾的checkSelectionChanged()方法么,这就是入口点。好了,上源码:

void checkSelectionChanged() {    if ((mSelectedPosition != mOldSelectedPosition) || (mSelectedRowId != mOldSelectedRowId)) {        // 如果positon和rowid有一个不一致,那么执行回调        selectionChanged();        mOldSelectedPosition = mSelectedPosition;        mOldSelectedRowId = mSelectedRowId;    }    // mPendingSelectionNotifier是一个SelectionNotifier对象。SelectionNotifier实现了Runnable接口,在run方法中实现了回调策略。mPendingSelectionNotifier.run和selectionChanged方法只会执行一个。原因是selectionChanged方法刚进去就会将mPendingSelectionNotifier设置为null    if (mPendingSelectionNotifier != null) {        mPendingSelectionNotifier.run();    }}

看看selectionChanged方法做了什么

void selectionChanged() {    // 就是在这里置null的。。    mPendingSelectionNotifier = null;    // 判断回调接口是否为null以及AccessibilityManager是否使能。AccessibilityManager管理着各种回调事件,如点击事件、焦点改变事件等等,在这里我们默认为true就好。    if (mOnItemSelectedListener != null            || AccessibilityManager.getInstance(mContext).isEnabled()) {        // 在之前的文章中提过这两个变量        // mInLayout会在Spinner.onLayout中被使能,在layout的过程中都是使能状态        // mBlockLayoutRequests在两个地方会使能        //     1.AbsSpinner.onMeasure方法中view设置LayoutParam的时候        //     2.setSelectionInt方法中        // 也就是说在以上三种情况使能状态下是不会进行直接回调,而是通过消息机制进行回调。        if (mInLayout || mBlockLayoutRequests) {            if (mSelectionNotifier == null) {                // 如果mSelectionNotifier为null那么创建一个                mSelectionNotifier = new SelectionNotifier();            } else {                // 如果mSelectionNotifier不为null,那么先从消息队列中移除该mSelectionNotifier                 removeCallbacks(mSelectionNotifier);            }            // 将mSelectionNotifier放入到消息队列中            post(mSelectionNotifier);        } else {        // 执行回调            dispatchOnItemSelected();        }    }}

再来看看SelectionNotifier中是如何处理回调的

private class SelectionNotifier implements Runnable {   public void run() {        mPendingSelectionNotifier = null;    // 如果此刻与发送该消息的时刻之间数据源发生了改变,也就是调用了adapter的notifyDataSetChanged或者notifyDataSetInvalidated方法,那么将此消息保存为mPendingSelectionNotifier。而mPendingSelectionNotifier会在下次layout结束的时候被调用。        if (mDataChanged && getViewRootImpl() != null                && getViewRootImpl().isLayoutRequested()) {            if (getAdapter() != null) {                mPendingSelectionNotifier = this;            }        } else {            // 数据源未发生改变,那么直接进行回调。            dispatchOnItemSelected();        }    }}

dispatchOnItemSelected()方法中还有一些东西,不过也比较简单,所以就不进行分析了。

好了Spinner的OnItemSelected事件的回调分析大致就是这样了。

以上。

0 0
原创粉丝点击