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