Wann müssen in einer Aktivität erstellte Rundfunkempfänger registriert / abgemeldet werden?

79

Ich muss im onCreate-Ereignis einer Aktivität einen benutzerdefinierten Broadcast-Empfänger erstellen, und natürlich muss ich die Registrierung des Broadcast-Empfängers im onDestroy-Ereignis der Aktivität aufheben

Aus Gründen der Klarheit ist dies ein Ausschnitt aus dem von mir verwendeten Code

public class AnActivity extends Activity {
    private ResponseReceiver receiver;

    public class ResponseReceiver extends BroadcastReceiver {
           public static final String ACTION_RESP =
              "mypackagename.intent.action.MESSAGE_PROCESSED";

           @Override
            public void onReceive(Context context, Intent intent) {
// TODO Start a dialogue if message indicates successfully posted to server
            }
    }   

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        IntentFilter filter = new IntentFilter(ResponseReceiver.ACTION_RESP);
        filter.addCategory(Intent.CATEGORY_DEFAULT);
        receiver = new ResponseReceiver();
        registerReceiver(receiver, filter);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(receiver);
    }

Ich habe gelesen, dass die Ereignisse onPause / onResume und onStart / onStop für die Aktivität auch den Rundfunkempfänger registrieren und die Registrierung aufheben sollten.

Ich möchte wirklich verstehen, was als beste Vorgehensweise dafür angesehen wird und warum.

jamesc
quelle
Dies liegt daran, dass beim onDestroy()Aufrufen keine Ereignisse mehr vom Empfänger abgehört werden.
de_billa_

Antworten:

91

Sie sollten Ihre Empfänger registrieren und die Registrierung aufheben onStart()und onStop().

Der einzige Grund, warum eine Aktivität BroadcastReceivers registrieren würde, besteht darin, die Ereignisse in irgendeiner Weise für die aktuelle Aktivität zu verwenden, um den Benutzer über ein Ereignis zu informieren. Wenn onStop()aufgerufen wurde, Activitysteht das nicht mehr im Vordergrund und kann daher den Benutzer nicht aktualisieren.

Wenn Sie Broadcast-Ereignisse im Hintergrund empfangen möchten, sollten Sie einen hier angegebenen Dienst in Betracht ziehen .

Wie Konstantin sagt, onDestroy()ist nicht garantiert, angerufen zu werden, und Sie könnten noch lange Sendungen empfangen, wenn die Activitynicht mehr geöffnet ist.

SnowyTracks
quelle
3
Schlagen Sie vor, dass ich mich bei onResume STATT onCreate oder so gut wie registriere? Wird onResume immer aufgerufen, wenn eine Aktivität erstellt wird?
Jamesc
9
Sie sollten onResume registrieren. Ja, onResume () wird immer für die angezeigte Aktivität aufgerufen (dies ist die letzte Methode, die aufgerufen wird, bevor Ihre Aktivität angezeigt wird ( developer.android.com/reference/android/app/Activity.html ), wenn Sie sich nur bei Create registrieren () und die Registrierung von onPause () aufheben. Wenn die Aktivität das nächste Mal in den Vordergrund gestellt wird, wird onCreate () nicht erneut aufgerufen und der Empfänger wird dann nicht erneut registriert. Und ja, ich meine STATT, tun Sie es nicht bei Create ().
SnowyTracks
1
@SnowyTracks: Können Sie kommentieren, warum es vorzuziehen ist, BroadcastReceiver-Registrierungsaufrufe in onResume / onPause anstatt in onStart / onStop durchzuführen? Mit Blick auf den Entwicklerleitfaden für gebundene Dienste, fand ich dies . Gegen Ende dieses Abschnitts wird empfohlen, die Dienstbindung / -entbindung in onStart / onStop und nicht in onResume / onPause (aus Leistungsgründen) durchzuführen. Ich frage mich, ob dies auch für BroadcastReceiver gilt. Danke im Voraus.
Janus Varmarken
1
@jvmk Einverstanden, das Android-Dokument sagt, dies in onStart und onStop zu tun. Ich denke, in 99% der Fälle macht es wenig Unterschied, es gibt nur einen Unterschied im Verhalten, wenn Dialogaktivitäten oder teilweise Vordergrundaktivitäten verwendet werden. Aber ich werde meine Antwort aktualisieren, um mit dem Android-Dokument
übereinzustimmen
1
Ich sehe, Sie haben gestern den 2. Absatz bearbeitet ... danke, dass Sie sich um eine konsistentere Antwort bemüht haben. Aber es erklärt immer noch nicht, warum man onStart / onStop anstelle von oder in Kombination mit onResume / onPause verwenden sollte , was die Frage des OP war. Stattdessen gilt die Erklärung des zweiten Absatzes für onResume / onPause ebenso wie für onStart / onStop: Sobald onPause aufgerufen wird, steht die Aktivität nicht mehr im Vordergrund. Wir haben also kein "Warum" für Ihre Empfehlung.
LarsH
19

Da onDestroy()es nicht garantiert ist, dass Sie angerufen werden, müssen Sie onPause()sich abmelden. Betrachten Sie den Lebenszyklus Ihres Rundfunkempfängers: Muss er nur dann aktiv sein, wenn Ihre Aktivität im Vordergrund steht? Dann benutze onResume()/onPause()

Konstantin Pribluda
quelle
Was ist, wenn wir den Inhalt der Aktivität auch dann aktualisieren müssen, wenn sich die Aktivität im Hintergrund befindet, da der Benutzer die App möglicherweise wieder aufnehmen kann und in diesem Fall aktualisierte Daten angezeigt werden sollten?
Usman Rana
9

Die Android-Dokumentation schreibt keinen einzigen Ort zum Registrieren / Aufheben der Registrierung von Rundfunkempfängern vor, nennt jedoch sowohl onStart()/ onStop()als auch onResume()/ onPause()als Möglichkeiten.

Der größte Faktor bei dieser Entscheidung ist, wann Ihr Empfänger seine Arbeit erledigen muss. Dadurch wird festgelegt, wann die Registrierung erfolgen und wann die Registrierung aufgehoben werden soll.

  • Muss der Empfänger nur dann etwas gegen die Sendung unternehmen, wenn die Aktivität im Fokus steht? Wenn ja, können Sie es in onPause()/ registrieren / abmelden onReceive(). (Sie können auch eine längere Lebensdauer wie onStart()/ verwenden onStop(), aber dann sollten Sie während des Empfängers prüfen, onReceive()ob die Aktivität im Fokus steht.)

  • Muss der Empfänger etwas tun, wenn er sichtbar ist, auch wenn er keinen Fokus hat (z. B. wenn ein Dialogfeld angezeigt wird)? Wenn ja, verwenden Sie onStart()/ onStop()(oder eine längere Lebensdauer, aber auch hier sollte der Empfänger onReceive()prüfen, ob die Aktivität sichtbar ist).

  • Muss der Empfänger über die Sendung Bescheid wissen, auch wenn die Aktivität nicht sichtbar ist? Zum Beispiel muss es nicht vergessen , dass etwas passiert ist, so dass , wenn die Aktivität wird sichtbar, kann es den resultierenden Zustand widerspiegelt? Dann müssen Sie onCreate()/ verwenden, um sich onDestroy()zu registrieren / die Registrierung aufzuheben. (Beachten Sie, dass es andere Möglichkeiten gibt, diese Art von Funktionalität zu implementieren.)

Wenn Sie sich registrieren onStart(), registrieren Sie sie nicht auch onResume(), da dies überflüssig wäre: Wird onResume()niemals aufgerufen, ohne onStart()vorher angerufen zu werden.

Denken Sie auch daran, dass es am besten ist , onPause () so hell wie möglich zu halten :

Die Ausführung von onPause () ist sehr kurz und bietet nicht unbedingt genügend Zeit, um Sicherungsvorgänge auszuführen. Aus diesem Grund sollten Sie onPause () nicht zum Speichern von Anwendungs- oder Benutzerdaten, zum Tätigen von Netzwerkaufrufen oder zum Ausführen von Datenbanktransaktionen verwenden. Diese Arbeiten werden möglicherweise nicht abgeschlossen, bevor die Methode abgeschlossen ist. Stattdessen sollten Sie während onStop () Schwerlast-Shutdown-Vorgänge ausführen.

Es stimmt , dass onDestroy()wird nicht aufgerufen werden garantiert , wenn das System Ihren Prozess , um Speicherplatz zu sparen tötet. Wenn der Prozess jedoch abgebrochen wird, empfängt der Prozess ohnehin keine Sendungen. Ist es in diesem Fall wirklich notwendig, die Registrierung von Rundfunkempfängern aufzuheben?

LarsH
quelle
Vielen Dank für Ihre Antwort auf meine Frage, aber Ihre Antwort ist verwirrend und nicht genau. Sie sagen, sie If you register in onStart(), don't also register them in onPause(), because that would be redundant: onPause() is never called without onStart() being called first.ist nur unlogisch und verwirrend, insbesondere wenn die akzeptierte Antwort vollkommen korrekt ist.
Jamesc
@jamesc: Ups, ich meinte eher onResume als onPause. Du hast recht, das ist ein bisschen verwirrend. Jetzt behoben. Die akzeptierte Antwort habe ich kommentiert. Ich glaube, diese Antwort fügt wichtige und relevante Informationen hinzu, die die akzeptierte nicht bietet.
LarsH
5

Android kann Ihre Anwendung durch Weglassen der onStop()Methode beenden . Der beste Weg, um diese Situation zu lösen, besteht darin, sich BroadcastReceiverin der onResume()Methode zu registrieren und die Registrierung in aufzuheben onPause().

Ukson
quelle
1
Ich mache das auch. Sie haben Probleme mit onStop()aswell
Vygintas B
0

Sie sollten Ihre Sendung mit den Methoden onResume () und onPause () registrieren und die Registrierung aufheben.

Wenn Sie sich in onStart () registrieren und die Registrierung in onStop () aufheben. Dieses Mal erhalten Sie folgendes Problem.

Wenn Ihr Gerätebildschirm gesperrt ist, wird onStop () aufgerufen, und wenn Sie diese Zeit entsperren, wird onStart () nie aufgerufen. Aus diesem Grund müssen Sie es in den Methoden onResume () und onPause () registrieren und die Registrierung aufheben.

Mayuresh Deshmukh
quelle