在最近的Google IO中,有一个有关实现宁静的客户端应用程序的演示。不幸的是,这只是一个高级别的讨论,没有实现的源代码。在此图中,返回路径上有各种不同的对其他方法的回调。



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

我了解回调的概念-发生特定事件后会调用的一段代码,但我不知道如何实现。到目前为止,我实现回调的唯一方法是重写各种方法(例如onActivityResult)。

我觉得我对设计模式有基本的了解,但我一直深陷其中如何处理返回路径。

评论

正是您所需要的。我一直在寻找同一件事,并且遇到了这个问题:javaworld.com/javaworld/javatips/jw-javatip10.html

#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/…

–乔迪
2013年12月6日12:31

我尝试在新活动中“实现” MyCallback接口,但该活动不成功,系统要求我在其上编辑源路径。那么我该如何从旧活动到新活动进行“回调”?

– Antoine Murion
15年4月20日在8:41

它说worker类中的回调变量对我而言为null

– iYonatan
16 Dec 8'在15:58

有人可以给kotlin等效吗?

– Tooniis
1月26日4:58

#2 楼

当我认为某件事发生时,我会触发一个我的活动正在监听的事件:

// DECLARED IN(CUSTOM)VIEW

    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教程很棒。经过几次试验,终于了解了如何使用回调。

– Moises Jimenez
2012年8月22日上午9:23

好答案。谢谢!

– iYonatan
16 Dec 8'在18:05

简单易懂。谢谢!

– Glenn J. Schworak
17年1月22日在13:49

#3 楼

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

评论


但是该怎么做呢?

– majurageerthan
2月18日下午6:01

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


主类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");
    }

}


评论


到目前为止,我们一直在使用接口进行回调,但是现在Square已经开发了一个lib作为event-bus Otto,它确实更快,更有用。

– Amol Patil
15年11月6日在8:26

#5 楼

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

Handler可以通过传递给Message用于在当前线程或另一个线程中执行回调s。 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方法内部?

– IgorGanapolsky
2013年9月23日下午3:55

+1为最佳答案。我更喜欢Callback版本,因为在构造它时,您不一定可以访问Runnable.run()所需的数据。

–柯比
16年6月30日在16:57

注意:“虽然Message的构造函数是公共的,但获取其中之一的最佳方法是调用Message.obtain()或Handler.obtainMessage()方法之一,这将从回收对象池中拉出它们。” - 从这里

– jk7
17年5月31日在18:04

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