如何在Android中定义回调?

How to Define Callbacks in Android?

提问人:user409841 提问时间:8/3/2010 最后编辑:Haywireuser409841 更新时间:2/15/2023 访问量:260932

问:

在最近的 Google IO 大会上,有一个关于实现 restful 客户端应用程序的演讲。不幸的是,这只是一个高层次的讨论,没有实现的源代码。

在此图中,在返回路径上,有对其他方法的各种不同回调。

google io presentation slide

如何声明这些方法是什么?

我理解回调的想法 - 在某个事件发生后调用的一段代码,但我不知道如何实现它。到目前为止,我实现回调的唯一方法是覆盖各种方法(例如onActivityResult)。

我觉得我对设计模式有基本的了解,但我总是在如何处理返回路径上被绊倒。

Android 回调

评论

3赞 Sid 10/1/2010
正是您所需要的。我一直在寻找同样的东西,并遇到了这个:javaworld.com/javaworld/javatips/jw-javatip10.html

答:

231赞 EboMike 8/4/2010 #1

在许多情况下,你有一个接口,并传递一个实现它的对象。例如,对话框具有 OnClickListener。

举个随机的例子:

// The callback interface
interface MyCallback {
    void callbackCall();
}

// The class that takes the callback
class Worker {
   MyCallback callback;

   void onEvent() {
      callback.callbackCall();
   }
}

// Option 1:

class Callback implements MyCallback {
   void callbackCall() {
      // callback code goes here
   }
}

worker.callback = new Callback();

// Option 2:

worker.callback = new MyCallback() {

   void callbackCall() {
      // callback code goes here
   }
};

我可能搞砸了选项 2 中的语法。现在还早。

评论

6赞 Jordy 12/6/2013
掌握此技术的一个很好的示例是,一个片段应如何通过其共享的 Activity 与另一个片段进行通信:developer.android.com/guide/components/...
0赞 Antoine Murion 4/20/2015
我尝试在新活动中“实现”MyCallback 接口,但没有成功,系统要求我编辑其上的源路径。那么,如何从旧活动到新活动进行“回调”呢?
3赞 iYonatan 12/8/2016
它说 worker 类中的回调变量对我来说是 null
1赞 Tooniis 1/26/2020
有人可以给出 kotlin 的等价物吗?
0赞 mdev 11/12/2022
人们希望的最简洁、最易理解的例子!
39赞 dragon 4/22/2012 #2

当可以使用现有接口时,无需定义新接口:。传递一个 Callback 类型的对象,并调用 callback 的 .android.os.Handler.CallbackhandleMessage(Message msg)

评论

0赞 majurageerthan 2/18/2020
但是该怎么做呢?
55赞 HGPB 7/21/2012 #3

在我看来,当某些事情发生时,我会触发我的活动正在侦听的事件:

在“(自定义)”视图中声明

    private OnScoreSavedListener onScoreSavedListener;
    public interface OnScoreSavedListener {
        public void onScoreSaved();
    }
    // ALLOWS YOU TO SET LISTENER && INVOKE THE OVERIDING METHOD 
    // FROM WITHIN ACTIVITY
    public void setOnScoreSavedListener(OnScoreSavedListener listener) {
        onScoreSavedListener = listener;
    }

在活动中声明

    MyCustomView slider = (MyCustomView) view.findViewById(R.id.slider)
    slider.setOnScoreSavedListener(new OnScoreSavedListener() {
        @Override
        public void onScoreSaved() {
            Log.v("","EVENT FIRED");
        }
    });

如果您想了解有关片段之间通信(回调)的更多信息,请参阅此处:http://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity

评论

1赞 Moises Jimenez 8/22/2012
那个 #CommunicatingWithActivity 教程很棒。经过几次尝试,终于明白了如何使用回调。
0赞 iYonatan 12/9/2016
很好的答案。谢谢!
0赞 Glenn J. Schworak 1/22/2017
简单易懂。谢谢!
22赞 MrGnu 10/19/2012 #4

澄清一下 Dragon 的答案(因为我花了一段时间才弄清楚该怎么做):Handler.Callback

Handler可用于在当前线程或其他线程中执行回调,方法是将回调中要使用的保留数据传递给它。a 可以传递给 的构造函数,以避免直接扩展 Handler。因此,要通过当前线程的回调来执行一些代码:MessageMessageHandler.CallbackHandler

Message message = new Message();
<set data to be passed to callback - eg message.obj, message.arg1 etc - here>

Callback callback = new Callback() {
    public boolean handleMessage(Message msg) {
        <code to be executed during callback>
    }
};

Handler handler = new Handler(callback);
handler.sendMessage(message);

编辑:刚刚意识到有一种更好的方法可以获得相同的结果(减去对何时执行回调的控制):

post(new Runnable() {
    @Override
    public void run() {
        <code to be executed during callback>
    }
});

评论

1赞 IgorGanapolsky 9/23/2013
您的 Runnable 帖子在 handleMessage 方法中?
0赞 Kirby 7/1/2016
+1 为最佳答案。我更喜欢这个版本,因为您可能不一定有权访问构建它时所需的数据CallbackRunnable.run()
0赞 jk7 6/1/2017
注意:“虽然 Message 的构造函数是公共的,但获取其中之一的最佳方法是调用 Message.obtain() 或 Handler.obtainMessage() 方法之一,这将从回收对象池中提取它们。
29赞 Amol Patil 7/17/2015 #5

使用接口实现回调方法的示例。

定义接口 NewInterface.java

软件包 javaapplication1;

public interface NewInterface {
    void callback();
}

创建一个新类 NewClass.java。它将调用主类中的回调方法。

package javaapplication1;

public class NewClass {

    private NewInterface mainClass;

    public NewClass(NewInterface mClass){
        mainClass = mClass;
    }

    public void calledFromMain(){
        //Do somthing...

        //call back main
        mainClass.callback();
    }
}

主类 JavaApplication1.java,用于实现接口 NewInterface - callback() 方法。它将创建并调用 NewClass 对象。然后,NewClass 对象将依次回调它的 callback() 方法。

package javaapplication1;
public class JavaApplication1 implements NewInterface{

    NewClass newClass;

    public static void main(String[] args) {

        System.out.println("test...");

        JavaApplication1 myApplication = new JavaApplication1();
        myApplication.doSomething();

    }

    private void doSomething(){
        newClass = new NewClass(this);
        newClass.calledFromMain();
    }

    @Override
    public void callback() {
        System.out.println("callback");
    }

}

评论

1赞 Amol Patil 11/6/2015
到目前为止,我们一直在使用接口进行回调,但现在Square已经开发了一个库作为事件总线Otto。它真的更快,很有帮助。
11赞 Rohit Mandiwal 8/29/2015 #6

您也可以用于此目的。这是一个快速指南LocalBroadcast

创建广播接收器:

   LocalBroadcastManager.getInstance(this).registerReceiver(
            mMessageReceiver, new IntentFilter("speedExceeded"));

private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Double currentSpeed = intent.getDoubleExtra("currentSpeed", 20);
        Double currentLatitude = intent.getDoubleExtra("latitude", 0);
        Double currentLongitude = intent.getDoubleExtra("longitude", 0);
        //  ... react to local broadcast message
    }

这就是触发它的方式

Intent intent = new Intent("speedExceeded");
intent.putExtra("currentSpeed", currentSpeed);
intent.putExtra("latitude", latitude);
intent.putExtra("longitude", longitude);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

在 onPause 中取消注册接收器:

protected void onPause() {
  super.onPause();
  LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
}
1赞 Mohammad 9/10/2021 #7

假设 main 函数是触发事件的活动:

fun main() {

val worker = Worker()

worker.setOnCallListener(
    object: OnCallListener {
        override fun onCall() {
            // here we define what should happen
            // when the event accures
            print("event happend")
        }
    }
)

// most events will be called from Android system itself
// but in our case we have to call it manually
worker.listener.onCall()
}

该类有一个 Type 接口的实例 以及设置其值的方法:WorkerOnCallListener

class Worker() {
    lateinit var listener: OnCallListener

    fun setOnCallListener(listener: OnCallListener) {
        this.listener = listener
    }
}

界面如下所示:OnCallListener

interface OnCallListener {
    fun onCall()
}