Spinner类OnItemSelected回调流程

上一篇文章 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值