Jak zdefiniować połączenia zwrotne w Androidzie?

Podczas najnowszego Google IO odbyła się prezentacja na temat wdrażania aplikacji klienckich restful. Niestety, była to tylko dyskusja na wysokim poziomie bez kodu źródłowego implementacji.

Na tym diagramie na ścieżce powrotnej znajdują się różne wywołania zwrotne do innych metod.

slajd prezentacji Google io

Jak mogę zadeklarować, czym są te metody?

Rozumiem ideę callback - kawałek kodu, który jest wywoływany po pewne wydarzenie się wydarzyło, ale nie wiem, jak je wdrożyć. Jedynym sposobem, w jaki zaimplementowałem wywołania zwrotne, było zastąpienie różnych metod (na przykład onActivityResult).

Czuję, że mam podstawową wiedzę na temat wzorca projektowego, ale ciągle się potkam, jak poradzić sobie ze ścieżką powrotną.

Author: Haywire, 2010-08-03

6 answers

W wielu przypadkach masz interfejs i przekazujesz obiekt, który go implementuje. Okna dialogowe mają na przykład OnClickListener.

Jako przykład losowy:

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

Prawdopodobnie pomieszałem składnię w opcji 2. Jest wcześnie.

 206
Author: EboMike,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-26 17:15:23

Kiedy coś się dzieje moim zdaniem odpalam zdarzenie, którego Moja aktywność słucha:

// ZADEKLAROWANE W (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;
    }

// DEKLAROWANE W DZIAŁALNOŚCI

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

Jeśli chcesz dowiedzieć się więcej o komunikacji (wywołaniach zwrotnych) między fragmentami, zajrzyj tutaj: http://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity

 48
Author: HGPB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-26 14:31:08

Nie ma potrzeby definiowania nowego interfejsu, gdy można użyć istniejącego: android.os.Handler.Callback. Przekazać obiekt typu Callback i wywołać callback handleMessage(Message msg).

 35
Author: dragon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-21 23:20:58

Aby wyjaśnić trochę odpowiedzi Smoka (ponieważ zajęło mi trochę czasu, aby dowiedzieć się, co zrobić z Handler.Callback):

Handler może być używany do wykonywania wywołań zwrotnych w bieżącym lub innym wątku, przekazując go Message s. Message przechowuje dane, które mają być użyte z wywołania zwrotnego. a Handler.Callback może być przekazane do konstruktora Handler w celu uniknięcia bezpośredniego rozszerzenia obsługi. tak więc, aby wykonać jakiś kod przez wywołanie zwrotne z bieżącego wątku:

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

EDIT: właśnie zdałem sobie sprawę, że jest lepszy sposób na ten sam wynik (minus Kontrola dokładnie kiedy wykonać wywołanie zwrotne):

post(new Runnable() {
    @Override
    public void run() {
        <code to be executed during callback>
    }
});
 19
Author: MrGnu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-19 15:20:05

Przykład implementacji metody callback przy użyciu interfejsu.

Zdefiniuj interfejs, NewInterface.java .

Pakiet javaapplication1;

public interface NewInterface {
    void callback();
}

Utwórz nową klasę, NewClass.java . Wywoła metodę callback w klasie main.

package javaapplication1;

public class NewClass {

    private NewInterface mainClass;

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

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

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

Główna klasa, JavaApplication1.java, aby zaimplementować metodę interfejsu NewInterface - callback (). Utworzy i wywoła obiekt NewClass. Następnie obiekt NewClass wywoła metodę callback () w odwróć się.

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

}
 19
Author: Amol Patil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-17 10:48:49

Możesz również użyć LocalBroadcast do tego celu. Oto szybki quide

Utwórz odbiornik transmisji:

   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
    }

Oto jak możesz go wyzwolić

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

Niezarejestrowany odbiorca w onPause:

protected void onPause() {
  super.onPause();
  LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
}
 10
Author: Rohit Mandiwal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-29 01:34:07