Android開發學習之路-記一次CSDN公開課

今天的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羣中提問了,獲得的答案可能是:都是回調,不明白他爲何這樣寫。我以爲吧,老是會有人硬是以爲它沒問題的,比較概念沒理解好,你也很難跟他說明。

相關文章
相關標籤/搜索