Java回调机制

推荐链接

Java中的回调

所谓回调

所谓回调,就是A类调用B类中的某个方法C,然后B类反过来调用A类中的某个方法D,这个D方法就叫回调方法。

异步+回调

  有一天小王遇到一个很难的问题,问题是“1 + 1 = ?”,就打电话问小李,小李一下子也不知道,就跟小王说,等我办完手上的事情,就去想想答案,小王也不会傻傻的拿着电话去等小李的答案吧,于是小王就对小李说,我还要去逛街,你知道了答案就打我电话告诉我,于是挂了电话,自己办自己的事情,过了一个小时,小李打了小王的电话,告诉他答案是2

方式一(经典)

3大前提:
  前提1:Class A实现回调接口CallBack
  前提2:class A中包含一个class B的引用
  前提3:class B有一个参数是接口Callback类型的方法 fun(CallBack callback, …)
2大步骤:
  第一步:利用Class A包含的class B引用去调用class B的方法 fun(CallBack callback, …) ——> A类调用B类的某个方法C
  第二步:class B在 fun(CallBack callback, …) 方法中调用Class A实现的接口方法 ——> B类调用A类的某个方法D

1
2
3
4
5
6
7
8
9
/**
* 回调接口
*/
public interface CallBack {
/**
* 小李告诉小王答案时要调用的函数,也就是回调函数
*/
public void solve(String result);
}
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
/**
* 前提1:Class A实现回调接口CallBack
*/
public class Wang implements CallBack {
/**
* 前提2:class A中包含一个class B的引用
*/
private Li li;

public Wang(Li li) {
this.li = li;
}

public void askQuestion(final String question) {
System.out.println("小王的问题--->" + question);
// 这里用一个线程就是异步,
new Thread(new Runnable() {
@Override
public void run() {
// A类调用B类的某个方法C
li.executeMessage(Wang.this, question);
}
}).start();

play();
}

public void play() {
System.out.println("小王逛街去了");
}

@Override
public void solve(String result) {
System.out.println("小李告诉小王的答案是--->" + result);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Li {
/**
* 前提3:class B有一个参数是接口Callback类型的方法 fun(CallBack callback, ...)
*/
public void executeMessage(CallBack callBack, String question) {
for (int i = 0; i < 10000; i++) {
//模拟小李办自己的事情需要很长时间
}
String result = "答案是2";
// B类调用A类的某个方法D
callBack.solve(result);
}
}
1
2
3
4
5
6
7
public class Test {
public static void main(String[] args) {
Li li = new Li();
Wang wang = new Wang(li);
wang.askQuestion("1 + 1 = ?");
}
}

方式二

前提:

  class B有一个参数是接口Callback类型的方法 fun(CallBack callback, …),并且class B内部定义了回调接口CallBack。
步骤:
  第一步:class A中获取(或创建)class B的引用。
  第二步:class B的引用调用class B的方法 fun(CallBack callback, …),CallBack类型的参数是匿名内部类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Wang {
public void askQuestion(final String question) {
final Li li = new Li();
System.out.println("小王的问题--->" + question);
// 这里用一个线程就是异步,
new Thread(new Runnable() {
@Override
public void run() {
li.executeMessage(new Li.CallBack() {
@Override
public void solve(String result) {
System.out.println("小李告诉小王的答案是--->" + result);
}
}, question);
}
}).start();

System.out.println("小王逛街去了");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
public class Li {
public void executeMessage(CallBack callBack, String question) {
for (int i = 0; i < 10000; i++) {
}
String result = "答案是2";
callBack.solve(result);
}

public interface CallBack {
void solve(String result);
}
}
1
2
3
4
5
6
public class Test {
public static void main(String[] args) {
Wang wang = new Wang();
wang.askQuestion("1 + 1 = ?");
}
}

同步+回调

上例方式二中把线程去掉就是同步回调

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Wang {
public void askQuestion(final String question) {
final Li li = new Li();
System.out.println("小王的问题--->" + question);

li.executeMessage(new Li.CallBack() {
@Override
public void solve(String result) {
System.out.println("小李告诉小王的答案是--->" + result);
}
}, question);

System.out.println("小王逛街去了");
}
}

经典的回调方法

线程 run() ,当执行 Thread 的 start() 方法就会回调这个 run() 方法。

Android 消息处理

Android View类的setOnClickListener方法