【问题标题】:How to Define Callbacks in Android?如何在 Android 中定义回调?
【发布时间】:2011-03-24 19:47:39
【问题描述】:

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

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

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

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

我觉得我对设计模式有了基本的了解,但我一直在如何处理返回路径上感到困惑。

【问题讨论】:

标签: android callback


【解决方案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 中的语法。现在还早。

【讨论】:

  • 掌握这种技术的一个很好的例子是一个片段应该如何通过它的共享活动与另一个片段进行通信:developer.android.com/guide/components/…
  • 我尝试在一个不成功的新活动中“实现”MyCallback 接口,系统要求我在其上编辑源路径。那么我将如何将旧活动的“回调”执行到新活动?
  • 它说worker类中的回调变量对我来说是null
  • 有人可以给 kotlin 等价物吗?
【解决方案2】:

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

// 在(自定义)视图中声明

    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

【讨论】:

  • #CommunicatingWithActivity 教程很棒。试了几次终于明白如何使用回调了。
  • 很好的答案。谢谢!
  • 简单易懂。谢谢!
【解决方案3】:

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

【讨论】:

  • 但是怎么做呢?
【解决方案4】:

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

定义接口,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();
    }
}

实现接口NewInterface的主类JavaApplication1.java - 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");
    }

}

【讨论】:

  • 直到现在我们都在使用回调接口,但现在 square 已经开发了一个作为事件总线 Otto 的库。它真的更快更有用。
【解决方案5】:

澄清一下龙的回答(因为我花了一段时间才弄清楚如何处理Handler.Callback):

Handler 可用于在当前或另一个线程中执行回调,方法是传递Messages。 Message 保存回调中要使用的数据。可以将Handler.Callback 传递给Handler 的构造函数,以避免直接扩展Handler。因此,通过当前线程的回调执行一些代码:

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>
    }
});

【讨论】:

  • 您的 Runnable 帖子在 handleMessage 方法中?
  • +1 以获得最佳答案。我更喜欢Callback 版本,因为您可能不一定能够访问Runnable.run() 在构建它时所需的数据
  • 注意:“虽然 Message 的构造函数是公共的,但获得其中之一的最佳方法是调用 Message.obtain() 或 Handler.obtainMessage() 方法之一,这将拉取它们来自回收对象池。” -- from here
【解决方案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);
}

【讨论】:

    【解决方案7】:

    假设主要功能是触发事件的活动:

    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()
    }
    

    Worker 类有一个类型为OnCallListener 接口的实例 以及设置其值的方法:

    class Worker() {
        lateinit var listener: OnCallListener
    
        fun setOnCallListener(listener: OnCallListener) {
            this.listener = listener
        }
    }
    

    OnCallListener 界面如下所示:

    interface OnCallListener {
        fun onCall()
    }
    

    【讨论】:

      猜你喜欢
      • 2016-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-15
      • 1970-01-01
      • 2020-07-31
      • 2014-03-08
      相关资源
      最近更新 更多