Androidでコールバックを定義する方法は?


152

最近のGoogle IOの間に、落ち着いたクライアントアプリケーションの実装に関するプレゼンテーションがありました。残念ながら、それは実装のソースコードなしの高レベルの議論にすぎませんでした。

この図では、戻りパスに他のメソッドへのさまざまなコールバックがあります。

google ioプレゼンテーションスライド

これらのメソッドを宣言するにはどうすればよいですか?

私はコールバックの概念を理解しています-特定のイベントが発生した後に呼び出されるコードの一部ですが、それを実装する方法がわかりません。これまでにコールバックを実装した唯一の方法は、さまざまなメソッド(たとえば、onActivityResult)をオーバーライドすることです。

設計パターンは基本的には理解できた気がしますが、帰り道の扱い方につまずき続けています。


3
まさにあなたが必要とするもの。私は同じことを探していて、これに遭遇しました:javaworld.com/javaworld/javatips/jw-javatip10.html
Sid

回答:


218

多くの場合、インターフェースがあり、それを実装するオブジェクトを渡します。たとえば、ダイアログには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の構文をめちゃくちゃにしました。


5
この技術上のグリップを得るための良い例では、フラグメントは、それが共有の活動を通じて別の断片と通信する方法である:developer.android.com/guide/components/...
ジョディ

成功しなかった新しいアクティビティでMyCallbackインターフェースを「実装」しようとしましたが、システムでソースパスを編集する必要があります。では、古いアクティビティから新しいアクティビティに「callBack」を実行するにはどうすればよいですか?
Antoine Murion、2015

3
ワーカークラスのコールバック変数は私にとってnullであると言っています
iYonatan

誰かがkotlinに同等のものを与えることができますか?
Tooniis

52

私の見解で何かが起こったとき、私は私の活動が聞いているイベントを発火します:

//(カスタム)ビューで宣言

    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
その#CommunicatingWithActivityチュートリアルは最高でした。最後に、いくつかの試行の後、コールバックの使用方法を理解しました。
モイゼスヒメネス

すばらしい答えです。ありがとう!
iYonatan 16

シンプルでわかりやすい。ありがとう!
Glenn J. Schworak 2017年

38

既存のインターフェースを使用できる場合は、新しいインターフェースを定義する必要はありませんandroid.os.Handler.Callback。タイプCallbackのオブジェクトを渡し、コールバックを呼び出しますhandleMessage(Message msg)


しかし、それを行う方法は?
majurageerthan

26

インターフェイスを使用してコールバックメソッドを実装する例。

インターフェース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-callback()メソッドを実装するメインクラス、JavaApplication1.java。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
これまでは、コールバックにインターフェイスを使用していましたが、squareはイベントバスOttoとしてlibを開発しました。これは本当に速くて便利です。
Amol Patil、2015年

20

ドラゴンの答えを少し明確にするために(何をどうするかを理解するのにしばらく時間がかかったのでHandler.Callback):

Handlerを渡すことにより、現在のスレッドまたは別のスレッドでコールバックを実行するために使用できますMessage。はMessage、コールバックから使用されるデータを保持します。ハンドラーを直接拡張しないようにするためにHandler.Callback、コンストラクターにa を渡すことができます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>
    }
});

1
Runnableの投稿はhandleMessageメソッド内にありますか?
IgorGanapolsky 2013

最良の答えを得るには+1。私のようなCallback、より良いバージョンあなたは、必ずしもで必要なデータへのアクセスを持っていない可能性があるのでRunnable.run()、あなたがそれを構築することを一度に
星のカービィ

注:「Messageのコンストラクターはパブリックですが、これらのいずれかを取得する最良の方法は、Message.obtain()またはHandler.obtainMessage()メソッドの1つを呼び出すことです。これにより、リサイクルされたオブジェクトのプールからそれらが取得されます。」- ここから
jk7

10

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);
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.