web-dev-qa-db-fra.com

Android équivalent à NSNotificationCenter

Lors du transfert d'une application iPhone sur Android, je recherche le meilleur moyen de communiquer au sein de l'application. Les intentions semblent être la voie à suivre, est-ce la meilleure (seule) option? NSUserDefaults semble beaucoup plus léger que les intentions en termes de performances et de codage.

Je devrais également ajouter que j'ai une sous-classe d'application pour state, mais que je dois informer une autre activité d'un événement.

83
John
6
Rui Peres

Le meilleur équivalent que j'ai trouvé est LocalBroadcastManager qui fait partie du Support Support Android

À partir de la documentation LocalBroadcastManager:

Aide pour s’inscrire et envoyer des émissions d’intentions à des objets locaux dans votre processus. Cela présente un certain nombre d'avantages par rapport à l'envoi d'émissions mondiales avec sendBroadcast (Intent):

  • Vous savez que les données que vous diffusez ne quitteront pas votre application, vous n'avez donc pas à vous soucier de la fuite de données privées.
  • Il n'est pas possible pour d'autres applications d'envoyer ces émissions à votre application, vous n'avez donc pas à craindre les failles de sécurité qu'elles peuvent exploiter.
  • C'est plus efficace que d'envoyer une diffusion globale à travers le système.

En l'utilisant, vous pouvez dire qu'une Intent est équivalente à un NSNotification. Voici un exemple:

ReceiverActivity.Java

Une activité qui surveille les notifications pour l'événement nommé "custom-event-name".

@Override
public void onCreate(Bundle savedInstanceState) {

  ...

  // Register to receive messages.
  // This is just like [[NSNotificationCenter defaultCenter] addObserver:...]
  // We are registering an observer (mMessageReceiver) to receive Intents
  // with actions named "custom-event-name".
  LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
      new IntentFilter("custom-event-name"));
}

// Our handler for received Intents. This will be called whenever an Intent
// with an action named "custom-event-name" is broadcasted.
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
    // Get extra data included in the Intent
    String message = intent.getStringExtra("message");
    Log.d("receiver", "Got message: " + message);
  }
};

@Override
protected void onDestroy() {
  // Unregister since the activity is about to be closed.
  // This is somewhat like [[NSNotificationCenter defaultCenter] removeObserver:name:object:] 
  LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
  super.onDestroy();
}

SenderActivity.Java

La deuxième activité qui envoie/diffuse des notifications.

@Override
public void onCreate(Bundle savedInstanceState) {

  ...

  // Every time a button is clicked, we want to broadcast a notification.
  findViewById(R.id.button_send).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
      sendMessage();
    }
  });
}

// Send an Intent with an action named "custom-event-name". The Intent sent should 
// be received by the ReceiverActivity.
private void sendMessage() {
  Log.d("sender", "Broadcasting message");
  Intent intent = new Intent("custom-event-name");
  // You can also include some extra data.
  intent.putExtra("message", "This is my message!");
  LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}

Avec le code ci-dessus, chaque fois que le bouton R.id.button_send est cliqué, une intention est diffusée et est reçue par mMessageReceiver dans ReceiverActivity.

La sortie de débogage devrait ressembler à ceci:

01-16 10:35:42.413: D/sender(356): Broadcasting message
01-16 10:35:42.421: D/receiver(356): Got message: This is my message! 
317
Shiki

Voici quelque chose de similaire à la réponse @Shiki, mais du point de vue des développeurs iOS et du centre de notification.

Commencez par créer un type de service NotificationCenter:

public class NotificationCenter {

 public static void addObserver(Context context, NotificationType notification, BroadcastReceiver responseHandler) {
    LocalBroadcastManager.getInstance(context).registerReceiver(responseHandler, new IntentFilter(notification.name()));
 }

 public static void removeObserver(Context context, BroadcastReceiver responseHandler) {
    LocalBroadcastManager.getInstance(context).unregisterReceiver(responseHandler);
 }

 public static void postNotification(Context context, NotificationType notification, HashMap<String, String> params) {
    Intent intent = new Intent(notification.name());
    // insert parameters if needed
    for(Map.Entry<String, String> entry : params.entrySet()) {
        String key = entry.getKey();
        String value = entry.getValue();
        intent.putExtra(key, value);
    }
    LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
 }
}

Ensuite, vous aurez également besoin d’un type d’énum pour être sûr des erreurs de codage avec des chaînes - (NotificationType):

public enum NotificationType {

   LoginResponse;
   // Others

}

Voici l'utilisation (ajouter/supprimer des observateurs) par exemple dans les activités:

public class LoginActivity extends AppCompatActivity{

    private BroadcastReceiver loginResponseReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
           // do what you need to do with parameters that you sent with notification

           //here is example how to get parameter "isSuccess" that is sent with notification
           Boolean result = Boolean.valueOf(intent.getStringExtra("isSuccess"));
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        //subscribe to notifications listener in onCreate of activity
        NotificationCenter.addObserver(this, NotificationType.LoginResponse, loginResponseReceiver);
    }

    @Override
    protected void onDestroy() {
        // Don't forget to unsubscribe from notifications listener
        NotificationCenter.removeObserver(this, loginResponseReceiver);
        super.onDestroy();
    }
}

et voici enfin comment nous envoyons une notification à NotificationCenter à partir d'un service de rappel ou de repos ou autre:

public void loginService(final Context context, String username, String password) {
    //do some async work, or rest call etc.
    //...

    //on response, when we want to trigger and send notification that our job is finished
    HashMap<String,String> params = new HashMap<String, String>();          
    params.put("isSuccess", String.valueOf(false));
    NotificationCenter.postNotification(context, NotificationType.LoginResponse, params);
}

c'est ça, à la vôtre!

9
Elvis Rudonja

Vous pouvez utiliser ceci: http://developer.Android.com/reference/Android/content/BroadcastReceiver.html , qui donne un comportement similaire.

Vous pouvez enregistrer les destinataires par programme via Context.registerReceiver (BroadcastReceiver, IntentFilter) et il capturera les intentions envoyées via Context.sendBroadcast (Intent).

Notez cependant qu'un destinataire ne recevra pas de notifications si son activité (contexte) a été suspendue. 

4
AngraX

J'ai constaté que l'utilisation d'EventBus of Guava lib est le moyen le plus simple de communication de type publication-abonnement entre composants sans nécessiter l'inscription explicite des composants

voir leur exemple sur https://code.google.com/p/guava-libraries/wiki/EventBusExplained

// Class is typically registered by the container.
class EventBusChangeRecorder {
  @Subscribe public void recordCustomerChange(ChangeEvent e) {
    recordChange(e.getChange());
  }

// somewhere during initialization
eventBus.register(this);

}

// much later
public void changeCustomer() {
  eventBus.post(new ChangeEvent("bla bla") );
} 

vous pouvez ajouter cette bibliothèque simplement sur Android Studio en ajoutant une dépendance à votre build.gradle:

compile 'com.google.guava:guava:17.0'
4
Shlomi Hasin

Vous pouvez utiliser des références faibles.

De cette façon, vous pouvez gérer vous-même la mémoire et ajouter et supprimer des observateurs à votre guise.

Lorsque vous ajoutez addObserver, ajoutez ces paramètres: convertissez le contexte de l'activité à laquelle vous l'ajoutez dans l'interface vide, ajoutez un nom de notification et appelez la méthode pour exécuter l'interface.

La méthode pour exécuter l'interface aurait une fonction appelée exécuter pour renvoyer les données que vous transmettez, par exemple.

public static interface Themethodtorun {
        void run(String notification_name, Object additional_data);
    }

Créez une classe d'observation qui appelle une référence avec une interface vide . Construisez également votre interface Themethodtorun à partir du contexte transmis dans le serveur addobserver.

Ajoutez l'observation à une structure de données.

Pour l'appeler, il s'agirait de la même méthode. Tout ce que vous avez à faire est de trouver le nom de la notification dans la structure de données. Utilisez le fichier Themethodtorun.run (nom_de_la_signalisation, data).

Cela enverra un rappel à l'endroit où vous avez créé un observateur avec un nom de notification spécifique . N'oubliez pas de les supprimer lorsque vous avez terminé!

C'est une bonne référence pour les références faibles.

http://learningviacode.blogspot.co.nz/2014/02/weak-references-in-Java.html

Je suis en train de télécharger ce code sur github. Gardez les yeux ouverts!

0
Victor Du Preez