wake-up-neo.com

Android-Äquivalent zu NSNotificationCenter

Beim Portieren einer iPhone-Anwendung auf Android suche ich nach dem besten Weg, um innerhalb der App zu kommunizieren. Absichten scheinen der Weg zu sein, ist dies die beste (einzige) Option? NSUserDefaults scheint in Bezug auf Leistung und Codierung viel leichter als Intents zu sein.

Ich sollte auch hinzufügen, dass ich eine Anwendungsunterklasse für den Status habe, aber ich muss eine andere Aktivität auf ein Ereignis aufmerksam machen.

83
John
6
Rui Peres

Das beste Äquivalent, das ich gefunden habe, ist LocalBroadcastManager , das Teil des Android Support Package ist. 

Aus der LocalBroadcastManager-Dokumentation:

Helfen Sie sich für die Registrierung und Übertragung von Intents-Sendungen an lokale Objekte in Ihrem Prozess. Dies hat eine Reihe von Vorteilen gegenüber dem Senden globaler Sendungen mit sendBroadcast (Intent):

  • Sie wissen, dass die von Ihnen gesendeten Daten Ihre App nicht verlassen werden. Machen Sie sich also keine Sorgen, dass private Daten verloren gehen.
  • Es ist nicht möglich, dass andere Anwendungen diese Broadcasts an Ihre App senden, sodass Sie sich keine Sorgen um Sicherheitslücken machen müssen, die sie ausnutzen können.
  • Es ist effizienter als das Senden einer globalen Sendung durch das System.

Wenn Sie dies verwenden, können Sie sagen, dass eine Intent eine Entsprechung zu einer NSNotification ist. Hier ist ein Beispiel:

ReceiverActivity.Java

Eine Aktivität, die auf Benachrichtigungen für das Ereignis mit dem Namen "custom-event-name" achtet.

@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

Die zweite Aktivität, die Benachrichtigungen sendet/sendet.

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

Mit dem obigen Code wird bei jedem Klicken auf die Schaltfläche R.id.button_send ein Intent gesendet und von mMessageReceiver in ReceiverActivity empfangen.

Die Debug-Ausgabe sollte folgendermaßen aussehen:

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

Hier ist etwas, das der @Shiki-Antwort ähnelt, jedoch aus Sicht der iOS-Entwickler und des Benachrichtigungszentrums.

Erstellen Sie zunächst eine Art NotificationCenter-Dienst:

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

Dann benötigen Sie auch einen Aufzählungstyp, um Fehler bei der Codierung mit Strings zu vermeiden - (NotificationType):

public enum NotificationType {

   LoginResponse;
   // Others

}

Hier ist Verwendung (Beobachter hinzufügen/entfernen) zum Beispiel in Aktivitäten:

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

und hier ist endlich, wie wir eine Benachrichtigung von einem Callback- oder Rest-Service oder was auch immer an das NotificationCenter senden:

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

das ist es, Prost!

9
Elvis Rudonja

Sie könnten Folgendes verwenden: http://developer.Android.com/reference/Android/content/BroadcastReceiver.html , was zu einem ähnlichen Verhalten führt.

Sie können Empfänger programmgesteuert über Context.registerReceiver (BroadcastReceiver, IntentFilter) registrieren, und es werden Absichten erfasst, die über Context.sendBroadcast (Intent) gesendet werden.

Beachten Sie jedoch, dass ein Empfänger keine Benachrichtigungen erhält, wenn seine Aktivität (Kontext) angehalten wurde. 

4
AngraX

Ich habe festgestellt, dass die Verwendung von EventBus von Guava lib der einfachste Weg für die Kommunikation im Publish-Subscribe-Stil zwischen Komponenten ist, ohne dass sich die Komponenten explizit miteinander registrieren müssen

ihr Beispiel finden Sie unter 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") );
} 

sie können diese Bibliothek einfach in Android Studio hinzufügen, indem Sie eine Abhängigkeit zu Ihrem build.gradle hinzufügen:

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

Sie könnten schwache Referenzen verwenden.

Auf diese Weise können Sie den Speicher selbst verwalten und nach Belieben Beobachter hinzufügen und entfernen.

Wenn Sie addObserver diese Parameter hinzufügen - fügen Sie diesen Kontext aus der Aktivität, zu der Sie ihn hinzufügen, zur leeren Schnittstelle hinzu, fügen Sie einen Benachrichtigungsnamen hinzu und rufen Sie die Methode zum Ausführen der Schnittstelle auf.

Die Methode zum Ausführen der Schnittstelle würde eine Funktion haben, die als run bezeichnet wird, um die Daten zurückzugeben, die Sie in etwa so übergeben

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

Erstellen Sie eine Beobachtungsklasse, die eine Referenz mit einer leeren Schnittstelle aufruft ..__ Erstellen Sie Ihre Themethodtorun-Schnittstelle auch aus dem Kontext, der im addobserver übergeben wird.

Fügen Sie die Beobachtung einer Datenstruktur hinzu.

Zum Aufrufen wäre es dieselbe Methode. Sie müssen jedoch nur den bestimmten Benachrichtigungsnamen in der Datenstruktur suchen. Verwenden Sie dazu die Methode Themethodtorun.run (notification_name, data).

Dadurch wird ein Rückruf an die Stelle gesendet, an der Sie einen Beobachter mit einem bestimmten Benachrichtigungsnamen erstellt haben. __ Vergessen Sie nicht, sie zu entfernen, wenn Sie fertig sind!

Dies ist eine gute Referenz für schwache Referenzen.

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

Ich bin gerade dabei, diesen Code in Github hochzuladen. Augen aufhalten!

0
Victor Du Preez