先抛一段代码
1 | public class CourseActivity extends AppCompatActivity { |
这段代码写了无数次,却对其内部的逻辑一直也没理会,现在总结下。
回调
在计算机程序设计中,回调函数,或简称回调(Callback 即call then back 被主函数调用运算后会返回主函数),是指通过函数参数传递到其它代码的,某一块可执行代码的引用。这一设计允许了底层代码调用在高层定义的子程序。 维基百科
通俗来讲,就是在 A 类 ( CourseActivity 类 ) 里调用 B 类 ( Button 类) 的 b 方法(setOnClickListener),然后在 B 类里的 b 方法(setOnClickListener),再回调 A 类里的 a 方法( onClick(View view) )。
现实中的例子
点外卖为例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
57
58
59
60/*
* 首先定义 We 类,代表我们本身
* 定义 TakeAway 类,代表外卖
* 定义 CallBack 接口,当外卖送到楼下后用于回调
* Main 函数中进行测试
*/
public class We implements CallBack{
private TakeAway takeAway=new TakeAway(); //外卖
//模仿一个人叫外卖
public void callTakeAway(){
//开启一个线程,用于调用外卖自己的方法,制作外卖,并且把自己类的实例传过去,让外卖回调自己
new Thread(new Runnable() {
public void run() {
takeAway.makeTakeAway(We.this);
}
}).start();
//点完外卖后,开始做其他事情,等待回调
System.out.println("我开始玩耍,静待外卖");
}
//外卖做好后会回调这个方法
public void getTakeAway() {
// TODO Auto-generated method stub
System.out.println("我拿到外卖了!开始吃吃吃!");
}
}
public class TakeAway {
//将接口作为入口参数,方便回调
void makeTakeAway(CallBack cb){
//睡眠 1 秒,模仿耗时工作
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("take-away:开始做外卖");
System.out.println("take-away:打包外卖");
System.out.println("take-away:送外卖");
System.out.println("take-away:到了楼下,\n开始回调「您好,您的外卖到了下来拿一下」");
//外卖做好,进行回调
cb.getTakeAway();
}
}
public interface CallBack {
void getTakeAway();
}
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
We I=new We();
I.callTakeAway();
}
}
运行结果如下图
探究源码
相关函数均定义在View类中
首先是回调的接口
1
2
3
4
5
6
7
8
9
10
11/**
* Interface definition for a callback to be invoked when a view is clicked.
*/
public interface OnClickListener {
/**
* Called when a view has been clicked.
*
* @param v The view that was clicked.
*/
void onClick(View v);
}传递要进行回调的对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14/**
* 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; //将传过来的对象保存
}执行回调函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22/**
* Call this view's OnClickListener, if it is defined. Performs all normal
* actions associated with clicking: reporting accessibility event, playing
* a sound, etc.
*
* @return True there was an assigned OnClickListener that was called, false
* otherwise is returned.
*/
public boolean performClick() {
final boolean result;
final ListenerInfo li = mListenerInfo;
if (li != null && li.mOnClickListener != null) {
playSoundEffect(SoundEffectConstants.CLICK);
li.mOnClickListener.onClick(this); //这里进行了回调
result = true;
} else {
result = false;
}
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
return result;
}要执行的东西就是我们继承了 View.OnClickListener 接口,实现的 onCLick() 方法了
1
2
3
4
public void onClick(View view) {
//do something
}
总结
源码只找了相关的部分,再细致自己目前也不会,慢慢学 QAQ ,总之,回调感觉就是利用多线程,先去完成一些事情,当事情完成后再利用传过来的对象,调用原来类的方法。