Как определить обратные вызовы в Android?

В течение самого последнего Google IO была презентация о внедрении непринужденных клиентских приложений. К сожалению, это было только обсуждение на высоком уровне без исходного кода реализации.

На этой диаграмме на пути возврата существуют различные разные обратные вызовы другим методам.

слайд презентации google io

Как объявить, что эти методы?

Я понимаю идею обратного вызова - фрагмент кода, который вызывается после того, как произошло определенное событие, но я не знаю, как его реализовать. Единственный способ, с помощью которого я реализовал обратные вызовы до сих пор, переопределял различные методы (например, onActivityResult).

Я чувствую, что у меня есть базовое понимание шаблона проектирования, но я продолжаю спотыкаться о том, как обрабатывать обратный путь.

Ответ 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. Это было раннее.

Ответ 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

Ответ 3

Нет необходимости определять новый интерфейс, если вы можете использовать существующий: android.os.Handler.Callback. Передайте объект типа Callback и вызовите обратный вызов handleMessage(Message msg).

Ответ 4

чтобы немного разъяснить ответ дракона (так как мне потребовалось некоторое время, чтобы выяснить, что делать с Handler.Callback):

Handler может использоваться для выполнения обратных вызовов в текущем или другом потоке, передавая его Message s. Message содержит данные, которые будут использоваться из обратного вызова. a 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);

EDIT: просто понял, что лучший способ получить тот же результат (минус контроль точно, когда нужно выполнить обратный вызов):

post(new Runnable() {
    @Override
    public void run() {
        <code to be executed during callback>
    }
});

Ответ 5

Пример реализации метода обратного вызова с использованием интерфейса.

Определите интерфейс, 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 будет обращать его обратный вызов() по очереди.

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

}

Ответ 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);

unRegister приемник в onPause:

protected void onPause() {
  super.onPause();
  LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
}