安卓回调机制

写安卓这么久了,对于回调一直没有深入研究。其实所谓的回调函数就是:在A类中定义了一个方法,这个方法中用到了一个接口和该接口中的抽象方法,但是抽象方法没有具体的实现,需要B类去实现,B类实现该方法后,它本身不会去调用该方法,而是传递给A类,供A类去调用,这种机制就称为回调。(参考系统的view的onClick()接口理解)

我的理解:老公要老婆做菜,老婆不知道老公想吃什么菜,那么就在老婆做菜的方法里传入一个做菜的接口,调用一个没实现的抽象方法,当老公让老婆做菜时调用做菜的方法,然后实现做菜接口,老婆的做菜方法里具体实现那个抽象方法,就可以想做什么菜接写什么代码啦,这样就做到了调用者想干什么自己实现的思想了。

其实网文一大推都在说,也不过是互相转载而已,这其中看到几篇比较不错的,这里转载一下。

1-----版权声明:^_^ 尊重原创,共享知识,转载请注明"_程序猿大人_"http://blog.csdn.net/a_running_wolf

什么是自定义回调函数?

        自定义回调函数,顾名思义,就是我们自己定义的回调函数。其实上边那个例子就是自定义回调函数!我们习惯上把别人定义好的回调函数叫作回调函数,Android系统中TextView、ImageView等和它们的子类控件的Onclick事件响应就是典型的回调机制。关于这个这位大虾讲得比我好——详细介绍Android中回调函数机制,详细看看会很有帮助的!


        一个简单的自定义回调函数的例子

        最后在举个简单的有代码的例子,看一下回调函数的运行过程:

        首先,我们定义一个interface:

[java] view plain copy
  1. public interface MyInterface {  
  2.     void sayYourName();  
  3. }  

        接着,我们定义一个类,其中一个方法以接口MyInterface类型的对象作为参数:

[java] view plain copy
  1. public class MyClass {  
  2.   
  3.     public MyClass() {  
  4.         Log.e("WangJ""MyClass-constructor");         //标注构造函数  
  5.     }  
  6.   
  7.     /* 用接口类型的对象作为输入参数 */  
  8.     public void sayYourName(MyInterface myInterface){  
  9.         Log.e("WangJ""MyClass-sayYourName_start");    //标注方法开始  
  10.         myInterface.sayYourName();                      //遇到不知道具体实现的时候就用接口的抽象方法  
  11.         Log.e("WangJ""MyClass-sayYourName_finish");   //方法结束  
  12.     }  
  13. }  

        最后,我们在Activity中调用这个类,创建对象并调用其方法,期间实现接口中抽象方法的具体实现逻辑,供回调使用:

[java] view plain copy
  1. public class MainActivity extends Activity {  
  2.   
  3.     @Override  
  4.     protected void onCreate(Bundle savedInstanceState) {  
  5.         super.onCreate(savedInstanceState);  
  6.         setContentView(R.layout.activity_main);  
  7.   
  8.         MyClass myClass = new MyClass();  
  9.         myClass.sayYourName(new MyInterface() {                     //实现接口并作为参数传入  
  10.             @Override  
  11.             public void sayYourName() {  
  12.                 Log.e("WangJ""callBack-interface-implementor");    //具体操作实现  
  13.             }  
  14.         });  
  15.     }  
  16. }  

        好了,运行一下(我们这个例子没有任何界面,即默认Activity的界面,看日志):

        

        运行的顺序就是我们之前理解的:在B中调用A中的方法,A中方法在运行到接口中抽象方法时返回B中寻找具体实现(这就是回调),回调完成后继续执行下边未完成的步骤。

2----参考http://blog.csdn.net/liushuaikobe/article/details/7934565

Java写了这么久的程序,一直没有理解什么是回调,在最近的Android开发工作中,一个偶然的需求让我突然就对Java中的回调有了一个理解,遂记录之。

  首先这个需求是这样的,一个Activity中的有一个View,我需要在不同的触发条件下更换这个View的Layout,我们很容易想到写一个方法,把要更换成的Layout的id传进去,然后为这个View设置一下content。就可以在不同的条件下调用这个函数来设置View的layout了,这不难理解。

  但是,假设,现在该View的Layout更换成了LayoutA,LayoutA里面有一个ImageView,我要对该ImageView通过代码设置一些属性;然后,另一时刻,该View的Layout换成了LayoutB,LayoutB里面有一个Button,我要对该Button通过代码做一些设置,怎么办?

  我们可以这样解决:

[java] view plain copy
  1. class MyActivity extends Activity {  
  2.     View view;  
  3.     int currentContentFlag;  
  4.   
  5.     private static final int ViewA = 1// 标志着当前View显示的内容是ViewA  
  6.     private static final int ViewB = 2// 标志着当前View显示的内容是ViewB  
  7.   
  8.     /** 
  9.     * 3.最后看这个函数 
  10.     */  
  11.     @Override  
  12.     public void onCreate(Bundle savedInstanceState) {  
  13.         super.onCreate(savedInstanceState);  
  14.         setContentView(R.layout.activity_main);  
  15.   
  16.         // 一些例如对view初始化工作略去  
  17.   
  18.         // 我们在这里设置View的layout的Id为layoutId_A  
  19.         currentContentFlag = ViewA; // 修改当前显示内容的flag,告诉这个setViewContent函数里面到底执行setViewA还是setViewB  
  20.         setViewContent(R.layout.layoutId_A);  
  21.     }  
  22.   
  23.     /** 
  24.     * 1.先看本函数 
  25.     */  
  26.     private void setViewContent(int layoutId) {  
  27.         view = LayoutInflater.from(this).inflate(layoutId, null); // 设置View的内容  
  28.         switch (currentContentFlag) {  
  29.             case ViewA:  
  30.                 // 说明当前View的内容是ViewA,在这里用代码对ViewA里面的东西进行具体设置  
  31.                 setViewA(view);  
  32.                 break;  
  33.             case ViewB:  
  34.                 // 说明当前View的内容是ViewB,在这里用代码对ViewB里面的东西进行具体设置  
  35.                 setViewB(view);  
  36.                 break;  
  37.             default :  
  38.                 break;  
  39.         }  
  40.     }  
  41.   
  42.     /** 
  43.     * 2.再看这两个函数 
  44.     */  
  45.     private setViewA(View view) {  
  46.   
  47.     }  
  48.   
  49.     private setViewB(View view) {  
  50.   
  51.     }  
  52. }  


  这样的话,每设置一次View的内容,都要修改当前显示内容的flag,通过维护这个flag变量,来告诉这个setViewContent函数里面到底执行setViewA还是setViewB。

  这样做可不可行呢?实现肯定也可以实现,但是,我想到了用回调机制来完成这件事。

  什么是回调呢?回调回调,回去调用。我理解回调,就是,在代码执行的过程中,函数FunA()某一时刻被调用,那么将转去执行FunA(),在FunA执行的时候呢,又反过来去执行原代码里的一些东西。这应该是最浅显的解释了吧。

  在Java语言里面,我们可以通过interface实现自己的回调,Java里面的interface真的太有用了。则上面的代码可以改为下面的实现:

[java] view plain copy
  1. class MyActivity extends Activity {  
  2.     View view;  
  3.   
  4.     /** 
  5.     * 3.看这个函数 
  6.     */  
  7.     @Override  
  8.     public void onCreate(Bundle savedInstanceState) {  
  9.         super.onCreate(savedInstanceState);  
  10.         setContentView(R.layout.activity_main);  
  11.   
  12.         // 一些例如对view初始化工作略去  
  13.   
  14.         // 我们在这里设置View的layout的Id为layoutId_A  
  15.         currentContentFlag = ViewA;   
  16.         setViewContent(R.layout.layoutId_A, new ConfigViewInterface() { // 传进去一个接口,并覆盖里面的方法  
  17.             public void setView(View view) {  
  18.                 setViewA(view);  
  19.             }  
  20.         });  
  21.     }  
  22.   
  23.     /** 
  24.     * 2.看本函数 
  25.     */  
  26.     private void setViewContent(int layoutId, ConfigViewInterface configViewInterface) {  
  27.         view = LayoutInflater.from(this).inflate(layoutId, null); // 设置View的内容  
  28.         configViewInterface.setView(view);  
  29.     }  
  30.   
  31.     /** 
  32.     * 4.看这两个函数 
  33.     */  
  34.     private setViewA(View view) {  
  35.   
  36.     }  
  37.   
  38.     private setViewB(View view) {  
  39.   
  40.     }  
  41.   
  42.     /** 
  43.     * 1.看本接口 
  44.     */  
  45.     private interface ConfigViewInterface {  
  46.         void setView(View view) ;  
  47.     }  
  48. }  

  这样是不是就好多了呢?慢慢理解下上面的代码,多少会对你有帮助的。有时候学知识,就要所练,可能当时不理解某个点,不知什么时候突然就懂了。

  欢迎拍砖。



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值