web-dev-qa-db-fra.com

Comment définir les rappels dans Android?

Lors de la dernière publication de Google IO, une présentation portait sur la mise en œuvre d'applications clientes reposantes. Malheureusement, il ne s’agissait que d’une discussion de haut niveau sans code source de l’implémentation.

Dans ce diagramme, sur le chemin de retour, il existe différents rappels à d'autres méthodes.

google io presentation slide

Comment déclarer ce que sont ces méthodes?

Je comprends l'idée d'un rappel - un morceau de code appelé après un certain événement, mais je ne sais pas comment le mettre en œuvre. Jusqu'à présent, la seule façon dont j'ai implémenté les rappels consistait à surcharger différentes méthodes (onActivityResult par exemple).

Je sens que j'ai une compréhension de base du modèle de conception, mais je continue à me demander comment gérer le chemin de retour.

148
user409841

Dans de nombreux cas, vous avez une interface et transmettez un objet qui l'implémente. Les boîtes de dialogue, par exemple, ont le OnClickListener.

Juste comme exemple aléatoire:

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

J'ai probablement foiré la syntaxe dans l'option 2. C'est tôt.

212
EboMike

Lorsque quelque chose se passe à mon sens, je déclenche un événement que mon activité écoute:

// DÉCLARÉ EN VUE (PERSONNALISÉE)

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

// DÉCLARÉ EN ACTIVITÉ

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

Si vous voulez en savoir plus sur la communication (rappels) entre fragments, voir ici: http://developer.Android.com/guide/components/fragments.html#CommunicatingWithActivity

50
HGPB

Pas besoin de définir une nouvelle interface lorsque vous pouvez utiliser une interface existante: Android.os.Handler.Callback. Transmettez un objet de type Callback et appelez le handleMessage(Message msg) du callback.

37
dragon

Exemple d'implémentation d'une méthode de rappel à l'aide d'une interface.

Définissez l'interface, NewInterface.Java.

package javaapplication1;

public interface NewInterface {
    void callback();
}

Créez une nouvelle classe, NewClass.Java. Il appellera la méthode de rappel en classe principale.

package javaapplication1;

public class NewClass {

    private NewInterface mainClass;

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

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

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

La classe principale, JavaApplication1.Java, permettant d'implémenter la méthode d'interface NewInterface - callback (). Il va créer et appeler l'objet NewClass. Ensuite, l'objet NewClass appellera sa méthode callback () à son tour.

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

}
25
Amol Patil

pour clarifier un peu la réponse de dragon (puisqu'il m'a fallu un certain temps pour savoir quoi faire avec Handler.Callback):

Handler peut être utilisé pour exécuter des rappels dans le fil actuel ou dans un autre thread en le transmettant Messages. la Message contient les données à utiliser à partir du rappel. un Handler.Callback peut être passé au constructeur de Handler afin d'éviter d'étendre directement Handler. ainsi, pour exécuter du code via callback à partir du thread actuel:

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: je viens de me rendre compte qu’il existe un meilleur moyen d’obtenir le même résultat (sans le contrôle du moment exact pour exécuter le rappel):

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

Vous pouvez également utiliser LocalBroadcast à cette fin. Voici un bref aperçu

Créer un récepteur de diffusion:

   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
    }

Voici comment vous pouvez le déclencher

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

unRegister receiver in onPause:

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