首页 > 什么是回调函数?一个类中的回调函数是什么作用

什么是回调函数?一个类中的回调函数是什么作用

一直搞不清楚~


Java是面向对象的,不存在回调函数这个说法。

回调函数是脚本语言之类的叫法,作为参数传递,在某个事件发生时执行的函数叫做回调函数。

function doSomething(finishCallBack){
    // 做事
    // 做完,调事件完成的回调函数。
    finishCallBack();
}

java能把方法作为参数传递吗?不能, 但是java有很多类似的机制可以实现这种所谓的“回调”,比如匿名内部类:

public interface FinishHandler{
    public void afterFinish();
}

public class SomeTask{
    public void doSomething(FinishHandler handler){
        // 做事
        handler.afterFinish(); // "回调"
    }
}

new SomeTask().doSomething(new FinishHandler(){
    public void afterFinish(){
        System.out.println("事情做完咯~~~")
    }
});

回调就是一种利用函数指针进行函数调用的过程. 通过回调,对象能够携带一些信息,这些信息允许它在稍后的某个时刻调用初始的对象。回调的价值在于它的灵活性,可以在运行时动态的决定需要调用什么方法。引用一段话:

使用回调函数实际上就是在调用某个函数(通常是API函数)时,将自己的一个函数(这个函数为回调函数)的地址作为参数传递给那个函数。而那个函数在需要的时候,利用传递的地址调用回调函数,这时你可以利用这个机会在回调函数中处理消息或完成一定的操作。

java的内部类实现了回调机制,在java的GUI中到处可以看到回调的例子。

详细查看:java编程思想第10章,提到了闭包和回调。Java8引入Lambda表达式,也是使用匿名内部类实现类似回调的机制。


就是它让别人去处理事情,处理完后把结果告诉它


一个类调用另一个类中的方法,前者称为调用者(caller),后者称为被调用者(callee),调用者就是发号施令的人,被调用者就是按要求执行命令的人。

通常,调用者需要做一件事情时,就会获取或创建一个被调用者的对象,然后调用它的方法,这是一种简单明了的关系,我们很容易就理解了。

而回调是这样一个过程:调用者那里事先有一些可能需要做的事情,被调用者把自己注册到调用者那里,然后对他说:“有事叫我”,有点毛遂自荐的意思。然后当一件事情发生时,被调用者就会根据事先注册的情况调用合适的方法来处理。

例如,我们向按钮(调用者)注册了一个点击事件的处理程序(被调用者),当点击事件发生时按钮就会找到这些处理程序并调用它们。

回调特别适合于那种调用者事先不知道应该由哪些类来负责处理某件事的情况

例如,编写按钮类的人不知道别人应该怎么处理按钮的点击事件,但他又不能不给按钮添加事件,否则按钮就没法正常使用了呀,这时候他就可以通过回调来解决这件事。


发现你最近也有提Android相关的问题,那我就通过Android ListView item的点击事件,一种使用频率很高的view,通过它认识“回调”,可能有助于理解。
比如ListView包含几个概略信息条目,你想点击某个条目跳到详情界面。
一般需要这样做:

mListView.setOnItemClickListener(mOnItemClickListener);

private OnItemClickListener mOnItemClickListener = new OnItemClickListener() {
  @Override
  public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    Intent intent = new Intent(getActivity(), DetailActivity.class);
    intent.putExtra(DetailActivity.ITEM_ID, position);
    startActivity(intent);
  }
}; 

当你这样做时,就已经实现了一个回调(implements a callback interface)。
接下来发生的事情我们就知道了,点某个条目就跳到其详情界面。
问题是,谁去调(call)它呢?我们在实现(implements)这个回调时,为什么必须要override其中的方法呢?

为了厘清这个问题,我们从点击事件发生时执行的代码看起:

// AdapterView.class, 这是ListView父类的父类

// 当view被点到时,performItemClick就被调到,处理点击带给view的变化,除此之外,
// AdapterView还想到了,“如果其它类想在点击发生时做点儿事情,该怎么办呢?”
// 通过接口。
// (1)我来定义接口,把知道的信息(被点到的view、position、id)告诉你;
// (2)你来实现接口,然后把实现的接口告诉我。

// 呐,这是我定义的接口。
255     public interface OnItemClickListener {
270         void onItemClick(AdapterView<?> parent, View view, int position, long id);
271     }

// 呐,你通过这个方法把实现的接口告诉我,我会存起来的。
279     public void setOnItemClickListener(OnItemClickListener listener) {
280         mOnItemClickListener = listener;
281     }

134     OnItemClickListener mOnItemClickListener;

// 那么现在点击事件发生了:
302     public boolean performItemClick(View view, int position, long id) {
            // 我先检查你是否实现了接口;
303         if (mOnItemClickListener != null) {
                // 嘿,该你回来做事情了。这就是callback,我call,你back。
305             mOnItemClickListener.onItemClick(this, view, position, id);
309             return true;
310         }
312         return false;
313     }

android.widget.AdapterView 源码链接

这是callback一种典型的应用场景。Android中有很多OnClickListener使用场景,看多了之后才对callback有些粗浅的认识,以前也是糊里糊涂的。
还有其它一些注册接口的形式,比如:register***Callbacks, unregister***Callbacks, remove***Callbacks

就是这样 :)

【热门文章】
【热门文章】