今天的CSDN公開課Android事件處理重難點快速掌握中老師講到一個概念我以爲不正確。html
原話是這樣的:點擊事件能夠經過事件監聽和回調兩種方法實現。android
我一聽到以後個人表情是這樣的:框架
這跟我學的看的都不同啊,這還分監聽和回調。這個時候我立馬提出問題,嗯,講課老師看到了。ide
老師就說了:是不同的,咱們第四點(最後一點)會講。佈局
好,我立馬坐好準備受教聽了大半小時。聽到最後個人表情是這樣的:post
廢話說夠了,開個小玩笑,不要見怪。學習
咱們都知道,監聽事件其實只有一種,就是回調。若是有人不明白什麼是回調?能夠看看個人一篇文章中的開頭那個例子:回調學習筆記ui
咱們以Button爲例,Button是View的子類這個毋庸置疑,因此咱們直接看View中的源碼:this
public void setOnClickListener(@Nullable OnClickListener l) { if (!isClickable()) { setClickable(true); } getListenerInfo().mOnClickListener = l; }
這裏很簡單,只是把一個OnClickListener的具體子類保存起來而已。當咱們點擊按鈕的時候,系統必然會回調onTouchEvent這個方法,而在View中這個方法是這樣的:spa
1 public boolean onTouchEvent(MotionEvent event) { 2 final float x = event.getX(); 3 final float y = event.getY(); 4 final int viewFlags = mViewFlags; 5 final int action = event.getAction(); 6 7 // 代碼省略 8 9 if (((viewFlags & CLICKABLE) == CLICKABLE || 10 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) || 11 (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) { 12 switch (action) { 13 case MotionEvent.ACTION_UP: 14 boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0; 15 if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) { 16 boolean focusTaken = false; 17 if (isFocusable() && isFocusableInTouchMode() && !isFocused()) { 18 focusTaken = requestFocus(); 19 } 20 21 if (prepressed) { 22 setPressed(true, x, y); 23 } 24 25 if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) { 26 if (!focusTaken) { 27 28 if (mPerformClick == null) { 29 mPerformClick = new PerformClick(); 30 } 31 if (!post(mPerformClick)) { 32 performClick(); 33 } 34 } 35 } 36 37 if (mUnsetPressedState == null) { 38 mUnsetPressedState = new UnsetPressedState(); 39 } 40 41 if (prepressed) { 42 postDelayed(mUnsetPressedState, 43 ViewConfiguration.getPressedStateDuration()); 44 } else if (!post(mUnsetPressedState)) { 45 mUnsetPressedState.run(); 46 } 47 48 removeTapCallback(); 49 } 50 mIgnoreNextUpEvent = false; 51 break; 52 53 case MotionEvent.ACTION_DOWN: 54 // 代碼省略 55 break; 56 57 case MotionEvent.ACTION_CANCEL: 58 // 代碼省略 59 break; 60 61 case MotionEvent.ACTION_MOVE: 62 // 代碼省略 63 break; 64 } 65 66 return true; 67 } 68 69 return false; 70 }
這裏我刪除了不少代碼,咱們知道一個點擊是由一個ACTION_DOWN、若干個ACTION_MOVE和一個ACTION_UP組成的,也就是說,當點擊完成,會執行ACTION_UP中的代碼。在第32行中,調用了一個方法叫作performClick,這個方法就是直接執行點擊事件的,咱們看到這個方法的內部:
1 public boolean performClick() { 2 final boolean result; 3 final ListenerInfo li = mListenerInfo; 4 if (li != null && li.mOnClickListener != null) { 5 playSoundEffect(SoundEffectConstants.CLICK); 6 li.mOnClickListener.onClick(this); 7 result = true; 8 } else { 9 result = false; 10 } 11 12 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); 13 return result; 14 }
第6行中,調用了咱們傳進來的那個接口的實現類中的onClick方法,這就是回調,由於這不是真正的調用。
總結:不管是什麼監聽事件,都是經過回調來實現的。咱們點擊以後,事件由系統捕獲,有底層控件逐步上傳到控件,而後回調給View的onTouchEvent方法,這個方法回調給咱們設置的接口中onClick方法。我當然知道回調和監聽不一樣,可是它們絕對不會是兩種方法。
我看到有人說李剛老師的《瘋狂Android講義》中確實是這麼定義的,我這裏補充說一下吧。書本認爲監聽和回調時兩種事件處理方法本就有誤。若是有去看過官方文檔,那麼其實在文檔中就有說到,內容以下:
翻譯:
在你用來構建佈局的各個View中,你可能已經注意到幾個共有的回調方法看上去對UI事件很是有用。這些方法會在對象發生相應動做的時候由Android框架調用。例如,當一個View(例如Button)被觸摸,這個View的onTouchEvent()方法會被執行。然而,爲了截獲這些事件,你必需要繼承這個類並重寫這些方法。爲了處理這些事件而繼承全部的View對象是不實際的。這就是爲何View類中包含一系列嵌套了一些帶有讓你更容易定義的回調的接口。這些接口,被稱爲事件監聽器,是你在你的UI中捕獲用戶行爲的憑證。
這裏說明了事件監聽器其實就是由回調方法組成的接口。也就會監聽器是由回調實現的。爲何要這樣呢?理由很簡單,由於咱們處理的操做通常是在活動中而不是在View中!
那麼究竟上面說的回調方法有哪些?在文檔的下部分中,列舉了幾個經常使用的回調:
哈哈,最後一次更新下。有人以爲李剛老師那麼厲害,不會錯的。我就說說個人見解吧,若是你認真去看《瘋狂Android講義》,你會發現,這本書的大部份內容就是翻譯和API介紹,說是Android開發的權威,我以爲甚至都稱不上。樓下有人也說到了,只要我去羣裏問一問,你們就能發現我是搞笑的,但實際上我也嘗試了,在知乎、微博或者QQ羣中提問了,獲得的答案可能是:都是回調,不明白他爲何這樣寫。我以爲吧,老是會有人硬是以爲它沒問題的,比較概念沒理解好,你也很難跟他說明。