web-dev-qa-db-ja.com

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

最新のGoogle IOでは、安らかなクライアントアプリケーションの実装に関するプレゼンテーションが行われました。残念ながら、実装のソースコードがなく、高レベルの議論にすぎませんでした。

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

google io presentation slide

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

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

デザインパターンの基本的な理解はあるように感じますが、リターンパスの処理方法についてはつまづきます。

148
user409841

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

211
EboMike

ビューで何かが発生すると、アクティビティがリッスンしているイベントを開始します。

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

50
HGPB

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

37
dragon

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

インターフェイス、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");
    }

}
24
Amol Patil

ドラゴンの答えを少し明確にするために(それはHandler.Callbackで何をすべきかを理解するのに時間がかかったので):

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

この目的で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);
}
11
Rohit Mandiwal