java中的回调机制

Android回调机制详解
作为新手,不得不说学习是个艰难的过程。这几天一直在看关于回调机制方面的问题,经过几天的摸索,开始对android中的回调机制有了一点理解,下面做一个记录,有的是从别处借鉴过来的,有的是自己的一点理解,如有错误或者遗漏之处,欢迎指正。

首先,什么是回调函数?android中怎么实现回调函数?为什么要使用回调函数?

    简单的说,回调函数就是通过其指针来调用的函数(这句话确实够简单的,下面会详细的描述);回调函数不会被自己所在的对象调用,只会在调用别人的方法的时候反过来被调用。我们知道android程序是通过java来实现的,java中是没指针的,那么怎么实现回调呢,通过接口、或者抽象类。

实现步骤:

1、定义一个接口,其中包含一个方法a;

2、定义一个实现这个接口的类A,实现方法  a(此处的a就是传说中的回调函数,此处不一定要在声明类的时候实现这个接口,也可以在类中去实现这个接口,我会分别举例子)

3、定义一个类B,在B中定义一个方法b,b以第一步中定义的接口作为参数;

4、在A中调用方法b,把自己作为参数传递进去;

5、在B中通过传递进来的参数A(实现了接口)去调用a,这就实现了回调;

 

    至于为什么要使用回调函数呢?在一位大神的博客里面看到这句话“回调功能是实现功能和定义分离的一种手段,是一种松耦合的设计思想”,有的人就会问了,为什么要实现定义和功能分离呢?我们在刚开始接触面向对象的这个概念的时候,应该经常听到这种说法:面向对象是要实现高内聚、低耦合,方便程序的修改和扩展。我觉得函数的定义和功能的分离应该也是这个道理吧。在下面的例子中我会在注释中从另外一个方面说明回调函数的必要性。

 

其次,看代码吧

代码1,在声明类的时候实现接口:

[java]  view plain copy
  1. package com.callback;  
  2.   
  3. /* 第一步:定义一个接口,其中包含一个方法a*/  
  4. public interface Callback {  
  5.     public void a(int i);  
  6. }  

[java]  view plain copy
  1. package com.callback;  
  2.   
  3. /* 第二步:定义一个实现这个接口的类A,实现方法  a*/  
  4. public class A implements Callback{  
  5.     static B b = new B();  
  6.     /* 此处为什么要定义一个常量呢? 
  7.      * 我是想从另一个方面(松耦合的设计思想算是一方面吧)说明回调方法的必要性, 
  8.      * 暂时先不用管,后面会继续说明的*/  
  9.     final int Constant = 1;  
  10.   
  11.     @Override  
  12.     /* 回调方法不会在A类中被调用的,注意看待会他会在哪被调用 */  
  13.     public void a(int result) {   
  14.         // TODO Auto-generated method stub                
  15.         System.out.println(result);  
  16.     }  
  17.       
  18.     public static void main(String[] args) {  
  19.         // TODO Auto-generated method stub  
  20.         /* 第四步:在A中调用方法b,把自己作为参数传递进去, 
  21.          * 此处A中的常量Constant,也会随着A被传到B中*/  
  22.         b.b(new A());  
  23.     }  
  24. }  


[java]  view plain copy
  1. <pre name="code" class="java">package com.callback;  
  2.   
  3. /* B中要干什么事呢? 
  4.  * 前面说过,回调函数要实现方法的定义和功能分离 
  5.  * 回调方法a是在A中定义的,其具体的功能会在B中来定义*/  
  6. public class B {  
  7.     A a = new A();  
  8.     /* 此处的常量跟A中的常量一样,后面我会解释的*/  
  9.     private final int Constant = 2;  
  10.   
  11.     /* 第三步:定义一个类B,在B中定义一个方法b,b以第一步中定义的接口作为参数*/  
  12.     public void b(A a) {  
  13.         // TODO Auto-generated method stub  
  14.         /* 此处也从另一个方面彰显了回调方法的作用. 
  15.          * 现在可以说说A、B中分别定义的两个常量的作用了 
  16.          * A中的常量其实没什么好说的,重要的是B中的常量, 
  17.          * 回调的方法a要实现的功能是将两个常量相加,并输出, 
  18.          * 但是B中的常量有时候A是无法访问的, 
  19.          * 就像现在,我把B中的常量定义为private的。 
  20.          * 打个比方,苹果公司要生产一批iphone,但是美国没有生产iphone的材料(假设的), 
  21.          * 只有生产iphone的技术,中国有生产iphone的材料, 
  22.          * 于是美国佬就拿着自己的技术来到中国,跟富士康的老大商量,让让富士康从中国获取材料, 
  23.          * 然后生产iphone,这里所说的美国就是A类,技术就是A中的常量了, 
  24.          * 中国就是B类,材料就是B类中的常量了,iphone就是result 
  25.          * 技术 + 材料 = 一部iphone*/  
  26.         int sum = a.Constant + this.Constant;  
  27.         a.a(sum);//第五步:在B中通过传递进来的参数A(实现了接口)去调用方法a  
  28.     }  
  29. }</pre><br>  


代码2,在类中实现接口:

其实我接下来要说的这种情况应该是android中最常见的使用回调机制的地方了,只是我们没有注意到罢了,

为Button添加事件监听的时候

[java]  view plain copy
  1. button.setOnClickListener(new View.OnClickListener() {  
  2.               
  3.     @Override  
  4.     public void onClick(View v) {  
  5.         // TODO Auto-generated method stub  
  6.         /***********/  
  7.     }  
  8. });  

其实就使用了回调机制,在上面的例子中,接口和B类是我们自己定义的,对应到这段代码中,其中的接口OnClickListener、类Button是系统定义好的,我们只需要拿过来用就行了

让我们来看看View的源码(很长的,只贴片段)

(为什么要看View的源码呢?因为Button是View的间接子类,View中的方法Button中都有)

[java]  view plain copy
  1. /** 
  2.      * Register a callback to be invoked when this view is clicked. If this view is not 
  3.      * clickable, it becomes clickable. 
  4.      * 
  5.      * @param l The callback that will run 
  6.      * 
  7.      * @see #setClickable(boolean) 
  8.      */  
  9.     public void setOnClickListener(OnClickListener l) {  
  10.         if (!isClickable()) {  
  11.             setClickable(true);  
  12.         }  
  13.         getListenerInfo().mOnClickListener = l;  
  14.     }  
看到其中的setOnClickListener()方法了吧,说明一下,此处的Button中的setOnClickListener()方法就相当于代码1中,B类中的b方法了,把接口 OnClickListener作为参数,

这就是传说中的在类中实现接口了 


再补充一点,在创建线程的时候,我们都知道一般有两种做法

[java]  view plain copy
  1. public class ClassName extends Object implements Runnable{  
  2.   
  3.     @Override  
  4.     public void run() {  
  5.         // TODO Auto-generated method stub  
  6.         /********/  
  7.     }  
  8. }  
还有一种

[java]  view plain copy
  1. Thread thread = new Thread(new Runnable(){  
  2.   
  3.         @Override  
  4.         public void run() {  
  5.             // TODO Auto-generated method stub  
  6.             /********/  
  7.         }  
  8.     });  
大家可能已经发现了,这两中创建线程的方法,都使用了回调机制,刚好对应着上面我举出的两个例子,在类声明的时候实现接口和在类中实现接口。
<think>好的,我现在要解决的问题是解释Java回调机制和监听事件之间的区别。用户可能对这两个概念有些混淆,需要明确它们的定义、应用场景和区别。首先,我需要回顾相关的知识,确保自己理解正确。 首先,回调机制。根据引用[3],回调是通过传递一个可执行对象(如接口或函数)到另一个方法中,在特定条件满足时触发执行。例如,学生类的gotoschool方法在完成后用callable.call()。这说明回调是一种通用的编程模式,用于异步通知或处理结果。 然后是监听事件。引用[2]提到事件源(如按钮)发生改变时触发监听器的操作。监听器模式通常包含事件源、事件对象和监听器。引用[1]指出监听器用于事件驱动编程,通过注册监听器来解耦组件。比如GUI中的按钮点击事件,用户点击按钮(事件源)时,监听器会处理事件。 接下来需要比较两者的区别。回调更广泛,是单向的通知机制,而监听器模式属于回调的一种具体实现,但更结构化。监听器通常涉及多个组件:事件源、事件、监听器,支持多监听器注册,实现观察者模式。而回调可能更简单,比如单一接口用。 需要确认两者在Java中的具体实现。引用[4]提到监听器的添加和移除方法,说明监听器模式允许动态管理监听器。而回调可能更直接,如传递一个回调接口到方法中,完成后用。 另外,引用[5]提到Redis的监听回调,可能结合了事件和回调机制,但需要区分通用概念和具体实现。 总结区别点:结构上,监听器模式更复杂,包含事件对象;回调更直接。应用场景上,监听器用于事件驱动系统,回调用于异步处理。注册方式上,监听器允许多个,回调通常是单一的。这些点需要清晰地在回答中呈现,并引用相关资料支持。 最后,要确保回答结构清晰,分点说明,并生成相关问题。需要检查是否覆盖了用户可能的疑问,比如使用场景、实现方式的不同等。</think>### Java 回调机制与监听事件的区别 #### 1. **定义与核心思想** - **回调机制** 回调是通过传递一个可执行对象(如接口、函数)到另一个方法中,在特定条件满足时触发执行。例如: ```java public interface Callable { void call(); } public class Student { public void gotoschool(int time, Callable callable) { // 异步操作完成后回调 callable.call(); // [^3] } } ``` 这里的`Callable`接口回调的载体,由用方实现,并在异步任务完成后触发。 - **监听事件** 监听器模式是回调的一种扩展实现,通常包含三个组件:**事件源**、**事件对象**、**监听器**。例如在GUI中: ```java button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { System.out.println("按钮被点击"); // [^2] } }); ``` 事件源(按钮)维护监听器列表,事件发生时遍历触发监听器的回调方法[^1]。 --- #### 2. **结构与实现差异** | **特性** | **回调机制** | **监听事件** | |----------------|--------------------------------|---------------------------------------| | **结构复杂度** | 简单(单向通知) | 复杂(包含事件对象、多监听器支持) | | **组件关系** | 直接传递回调接口 | 事件源、监听器、事件对象三者解耦 | | **注册方式** | 通常单次绑定(如方法参数) | 支持动态添加/移除监听器(如`addXxxListener`)[^4] | | **典型应用** | 异步任务完成通知 | GUI事件、消息队列监听(如Redis键空间通知[^5]) | --- #### 3. **应用场景** - **回调机制** 适用于需要异步通知的场景,例如: - 网络请求完成后更新UI。 - 多线程任务执行结果返回。 - **监听事件** 适用于事件驱动型系统,例如: - GUI组件交互(按钮点击、窗口关闭)。 - 系统级事件监听(如Redis键过期通知)。 --- #### 4. **关键区别总结** 1. **模式范畴** 回调是通用编程范式,而监听器是回调的一种具体实现形式[^1]。 2. **组件关系** 监听器模式通过事件对象传递详细信息(如`ActionEvent`),而回调通常仅传递简单信号。 3. **扩展性** 监听器支持多个监听器注册,实现观察者模式;回调通常是一对一的关系。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值