从一开始接触回调机制到现在,一直不太明白这其中的过程和原理。直到最近在网上混了很久,才突然明白。
这对于我这个Android小白还是一件很值得开心的事情。
今天特此在这里写下来我对回调机制的愚见,也做个留念。
下面就从一个小故事开始说起。
----------------------------------------------------------------------
华丽的分割线
----------------------------------------------------------------------
有一天皇帝乾隆(King)想知道地方政府苏州(Local)抓贼怎么样,生产粮食怎么样,就找来一个钦差大臣小栓子(QinChai)说,你给我去地方看看,要是抓贼到20有赏,生产50顿粮食有赏。
于是小栓子就带着圣旨去了苏州。到了苏州,小栓子也不说话,就看着。
皇帝和地方本来知道有钦差大臣这个职位,有这个概念,和钦差的作用,监管地方,执行皇帝命令。(接口及其方法)
苏州官府上也有钦差大臣的住处。
这小栓子一来,就给安排到这住处。
而苏州地方每天依然抓贼,产粮食。小栓子也跟着看着。
直到有一天,苏州抓贼满20个了。这时候小栓子掏出了乾隆的圣旨,“奉天承运,皇帝诏曰:赏银千两”。
又有一天,粮食产到50吨了。小栓子又掏出圣旨,“奉天承运,皇帝诏曰:赏金万两”。
到这,乾隆的两个圣旨被小栓子下达执行了。
----------------------------------------------------------------------
华丽的分割线
----------------------------------------------------------------------
讲这个小故事是什么意思呢?其实这个故事里蕴含了回调机制的真谛。那么这个真谛是什么呢?暂且不急,我们先用代码来实现上面那个小故事。
钦差大臣这个官职(接口)
package callback.test;
public interface QinChai {
/*这个QinChai(钦差)的官职拥有这两个权利,但是具体该怎么做是皇帝下达
* 这其实就是一个Listener
*/
//看地方逮小偷
public void onCatchTheftDone();
//看地方生产粮食
public void onMakeGrainDone();
}<strong>
</strong>
King类 (想)
package callback.test;
public class King {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
King qianLong = new King();
qianLong.wantToKnowLocal();
}
public King(){
}
public void wantToKnowLocal(){
System.out.println("乾隆:朕想知道苏州逮了多少贼,生产多少粮食");
Local suZhou = new Local();
System.out.println("乾隆:小栓子,你给我去看看,要是逮贼50赏银千两;产量50吨赏金万两!");
//乾隆把小栓子派到苏州去了,并告诉小栓子该怎么做
suZhou.welcomeQinChai(new QinChai(){
public void onCatchTheftDone() {
// TODO Auto-generated method stub
System.out.println("小栓子:奉天承运,皇帝诏曰:逮贼20,赏银千两!");
}
public void onMakeGrainDone() {
// TODO Auto-generated method stub
System.out.println("小栓子:奉天承运,皇帝诏曰:产粮50,赏金万两!");
}
});
}
}
地方类
package callback.test;
public class Local{
//钦差这个位置,在小栓子没来之前都是空着的
private QinChai qinChaiDaRen = null;
private Thread catchTheft = null;
private Thread makeGrain = null;
private Thread otherThing = null;
public Local(){
localShouldDo();
doLocalShouldDo();
}
private void localShouldDo(){
System.out.println("地方:我可以逮贼,产粮,做其他事!");
catchTheft = new Thread(){
public void run() {
super.run();
catchTheft();
}
};
makeGrain = new Thread(){
public void run() {
super.run();
makeGrain();
}
};
otherThing = new Thread(){
public void run() {
super.run();
doOther();
}
};
}
private void doLocalShouldDo(){
System.out.println("地方:开始干活");
catchTheft.start();
makeGrain.start();
otherThing.start();
}
private void catchTheft(){
for(int i = 0;i < 40;i++){
System.out.println("地方:逮贼" + i + "个");
if(null != qinChaiDaRen && i == 20){
qinChaiDaRen.onCatchTheftDone();
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private void makeGrain(){
for(int i = 0;i < 60;i++){
System.out.println("地方:产粮" + i + "吨");
if(null != qinChaiDaRen && i == 50){
qinChaiDaRen.onMakeGrainDone();
}
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
private void doOther(){
System.out.println("地方:其他事情。。。");
}
public void welcomeQinChai(QinChai qinchai){
System.out.println("地方:欢迎钦差大人!");
this.qinChaiDaRen = qinchai;
}
}
运行结果:
乾隆:朕想知道苏州逮了多少贼,生产多少粮食
地方:我可以逮贼,产粮,做其他事!
地方:开始干活
乾隆:小栓子,你给我去看看,要是逮贼20赏银千两;产量50吨赏金万两!
地方:其他事情。。。
地方:逮贼0个
地方:产粮0吨
地方:欢迎钦差大人!
地方:产粮1吨
地方:逮贼1个
地方:逮贼2个
地方:产粮2吨
地方:产粮3吨
地方:逮贼3个
地方:产粮4吨
地方:逮贼4个
地方:逮贼5个
地方:产粮5吨
地方:产粮6吨
地方:逮贼6个
地方:产粮7吨
地方:逮贼7个
地方:逮贼8个
地方:产粮8吨
地方:逮贼9个
地方:产粮9吨
地方:产粮10吨
地方:逮贼10个
地方:逮贼11个
地方:产粮11吨
地方:产粮12吨
地方:逮贼12个
地方:逮贼13个
地方:产粮13吨
地方:逮贼14个
地方:产粮14吨
地方:逮贼15个
地方:产粮15吨
地方:产粮16吨
地方:逮贼16个
地方:逮贼17个
地方:产粮17吨
地方:逮贼18个
地方:产粮18吨
地方:产粮19吨
地方:逮贼19个
地方:产粮20吨
地方:逮贼20个
小栓子:奉天承运,皇帝诏曰:逮贼20,赏银千两!
地方:产粮21吨
地方:逮贼21个
地方:逮贼22个
地方:产粮22吨
地方:逮贼23个
地方:产粮23吨
地方:逮贼24个
地方:产粮24吨
地方:逮贼25个
地方:产粮25吨
地方:产粮26吨
地方:逮贼26个
地方:产粮27吨
地方:逮贼27个
地方:产粮28吨
地方:逮贼28个
地方:逮贼29个
地方:产粮29吨
地方:产粮30吨
地方:逮贼30个
地方:产粮31吨
地方:逮贼31个
地方:产粮32吨
地方:逮贼32个
地方:产粮33吨
地方:逮贼33个
地方:产粮34吨
地方:逮贼34个
地方:逮贼35个
地方:产粮35吨
地方:逮贼36个
地方:产粮36吨
地方:产粮37吨
地方:逮贼37个
地方:产粮38吨
地方:逮贼38个
地方:逮贼39个
地方:产粮39吨
地方:产粮40吨
地方:产粮41吨
地方:产粮42吨
地方:产粮43吨
地方:产粮44吨
地方:产粮45吨
地方:产粮46吨
地方:产粮47吨
地方:产粮48吨
地方:产粮49吨
地方:产粮50吨
小栓子:奉天承运,皇帝诏曰:产粮50,赏金万两!
地方:产粮51吨
地方:产粮52吨
地方:产粮53吨
地方:产粮54吨
地方:产粮55吨
地方:产粮56吨
地方:产粮57吨
地方:产粮58吨
地方:产粮59吨
从上面的结果可以看出:
小栓子在地方逮贼到20和产量到50的时候分别颁布圣旨进行赏赐。而这是乾隆所事先告诉好的。
----------------------------------------------------------------------
华丽的分割线
----------------------------------------------------------------------
从这个有趣的故事里走出来。
小栓子:定义的一个接口,并声明了某些功能。但是不能自己实现。
乾隆:监听的发起者,创建接口实例,实现接口的功能,并把这个接口传给想监听的类。
地方(苏州):被监听者,提供接纳接口实例的setter函数(welcomeQinchai),并有容纳这个实例的位置(如上例中,地方留着的钦差大臣的位置)。
所以,就到回调机制的真谛了。通过 被监听者的setter函数 将监听发起者创建的接口实例传给了被监听者。所以被监听者 通过引用这个实例就可以在条件满足时 调用监听者已经实现的内容。