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

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

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

google io presentation slide

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

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

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

6 ответов


во многих случаях у вас есть интерфейс и вы передаете объект, который его реализует. Диалоги к примеру у 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. Еще рано.


когда что-то происходит на мой взгляд, я запускаю событие, которое моя деятельность слушает:

/ / ОБЪЯВЛЕНО В (ПОЛЬЗОВАТЕЛЬСКОМ) ПРЕДСТАВЛЕНИИ

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

/ / ОБЪЯВЛЕНО В ACTIVITY

    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


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


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

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

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

определить интерфейс, 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");
    }

}

вы также можете использовать 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);
}