工作總結(jié)|Android關(guān)于onKeyUp回調(diào)不執(zhí)行的問題分析

前段時間在修改一個關(guān)于按鍵事件點擊的bug,讓猿對Android的事件傳遞有了更深的了解,現(xiàn)在分享出來給大家。

需求描述

當(dāng)頁面中ListView處于選擇態(tài)時,當(dāng)?shù)谝淮吸c擊Back鍵需要將ListView的選擇態(tài)清除,點擊第二次Back鍵時,頁面才關(guān)閉退出。

需求實現(xiàn)

在頁面Activity中重寫了onBackPressed()方法,ListView中重寫了View的onKeyUp方法,當(dāng)ListView中如果是點擊態(tài)時,在onKeyUp中攔截事件,并清除ListView的選擇態(tài),并return True攔截按鍵事件返回。

問題描述

在調(diào)試過程中發(fā)現(xiàn):當(dāng)頁面中ListView處于選擇態(tài)時,點擊Back鍵時,頁面直接關(guān)閉。程序并不執(zhí)行ListView中的onKeyUp方法。

出現(xiàn)原因

在頁面初始化后,在選擇ListView為選擇態(tài)結(jié)束后,調(diào)用了ListView.clearFocus()方法,導(dǎo)致了ListView的onKeyUp方法不回調(diào)。

原因分析

我們大概都知道,Android事件傳遞從上到下傳遞,而對于KeyEvent來說,ViewGroup中分發(fā)事件方法代碼中有這樣一段:

@Override
public boolean dispatchKeyEvent(KeyEvent event) {
    if (mInputEventConsistencyVerifier != null) {
        mInputEventConsistencyVerifier.onKeyEvent(event, 1);
    }

    if ((mPrivateFlags & (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS))
            == (PFLAG_FOCUSED | PFLAG_HAS_BOUNDS)) {
        if (super.dispatchKeyEvent(event)) {
            return true;
        }
    } else if (mFocused != null && (mFocused.mPrivateFlags & PFLAG_HAS_BOUNDS)
            == PFLAG_HAS_BOUNDS) {
        if (mFocused.dispatchKeyEvent(event)) {
            return true;
        }
    }

    if (mInputEventConsistencyVerifier != null) {
        mInputEventConsistencyVerifier.onUnhandledEvent(event, 1);
    }
    return false;
}

我們可以看到,在ViewGroup中,會對mFocused這個View進(jìn)行判斷,如果它不為空,有焦點,才會由他去分發(fā)事件,最終才有可能執(zhí)行它的回調(diào)方法。所以如果我們手動調(diào)用clearFocus后,使當(dāng)前FocusView為空,自然就無法最終執(zhí)行其回調(diào)方法了。

事實上,當(dāng)Activity中dispatcherKeyEvent時,是通過Activity中的PhoneWindow綁定的DecoderView進(jìn)行分發(fā)的,DecoderView最終通過ViewGroup的dispatcherKeyEvent將事件分發(fā)出去。詳細(xì)的事件分發(fā)流程會在后續(xù)文章中進(jìn)行詳細(xì)分析。請大家期待O(∩_∩)O

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容