Android开发学习教程(7)- 详解Android Button点击事件原理
—— 只有你成功了,才有选择的权力,才会被更多的人尊重。
上一篇我们知道了Button的基本用法,最后讲到了Button的点击事件是通过setOnClickListener方法来实现的。那么APP是如果把用户的点击动作和setOnClickListener关联起来的呢,要弄明白这个问题,我们先来看看APP中是什么时侯处理用户点击动作的。要看问题还得从代码看起,这里以上一篇中的Button基本用法项目举例,打开TestActivity点击事件的主要代码:
1
2
3
4
5
6
button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(TestActivity.this, "我被点击了", Toast.LENGTH_SHORT).show(); }});我们来看setOnClickListener的源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/** * Register a callback to be invoked when this view is clicked. If this view is not * clickable, it becomes clickable. * * @param l The callback that will run * * @see #setClickable(boolean) */public void setOnClickListener(@Nullable OnClickListener l) { if (!isClickable()) { setClickable(true); } getListenerInfo().mOnClickListener = l;}注释写的很明白,注册一个当view被点击时的回调方法。可以看到把回调方案OnClickListener传给了getListenerInfo().mOnClickListener,getListenerInfo()跟进去:static class ListenerInfo { @UnsupportedAppUsage ListenerInfo() { }......}一个静态类而已,里面定义了一堆接口,包括上面传递的点击事件mOnClickListener ,那么mOnClickListener 什么时侯被调用,view里面有一个onTouchEvent方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/***实现此方法以处理触摸屏幕移动事件。*包括:*1. 播放单击声音*2. 调用OnClickListener*/public boolean onTouchEvent(MotionEvent event) { ......// 如果是可点击的 if (clickable) { switch (action) {// ACTION_UP 手指触摸屏幕抬起事件 case MotionEvent.ACTION_UP: ...// 如果不可点击的,那么移出所有相关回调,并跳出循环 if (!clickable) { removeTapCallback(); removeLongPressCallback(); mInContextButtonPress = false; mHasPerformedLongPress = false; mIgnoreNextUpEvent = false; break; }// 如果view是被按下的状态(说明在手指按下时按的是这个view) if (prepressed) { boolean focusTaken = false; if (isFocusable() && isFocusableInTouchMode() && !isFocused()) { focusTaken = requestFocus(); } // 设置按下状态 if (prepressed) { setPressed(true, x, y); } if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {// 能到这一步说明是单击事件,那么移除长按事件的回调 removeLongPressCallback(); if (!focusTaken) { // 创建一个执行点击回调的子线程 if (mPerformClick == null) { mPerformClick = new PerformClick(); }// 把子线程添加到UI线程的消息对列中等待处理 if (!post(mPerformClick)) { performClickInternal(); } } } ... removeTapCallback(); }上面那个执行点击回调的子线程:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public boolean performClick() { ... final boolean result;// 这里的mListenerInfo就是我们在Activity中setOnClickListener传递过来的 final ListenerInfo li = mListenerInfo; if (li != null && li.mOnClickListener != null) { playSoundEffect(SoundEffectConstants.CLICK);// 具体在这执行回调,即Activity中的public void onClick(View v) {...} li.mOnClickListener.onClick(this); result = true; } else { result = false; } ... return result;}源码链接:https://yunjunet.cn/876732.html

