BroadcastReceiver mit mehreren Filtern oder mehreren BroadcastReceivern?

114

Ich habe eine Android-Aktivität, die zwei verschiedene Sendungen abfangen muss. Mein aktueller Ansatz ist es, eine Single BroadcastReceiverinnerhalb der Aktivität zu haben und beide Sendungen damit zu erfassen:

public class MyActivity extends Activity {
    private MyActivity.BroadcastListener mBroadcastListener;
    private boolean mIsActivityPaused = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mylayout);

        // Create the broadcast listener and register the filters
        mIsActivityPaused = false;
        mBroadcastListener = new BroadcastListener();

        IntentFilter filter = new IntentFilter();
        filter.addAction(Params.INTENT_REFRESH);
        filter.addAction(Params.INTENT_UPDATE);
        registerReceiver(mBroadcastListener, filter);
    }

    @Override
    protected void onResume() {
        super.onResume();
        mIsActivityPaused = false;
    }

    @Override
    protected void onPause() {
        super.onPause();
        mIsActivityPaused = true;
    }

    @Override
    protected void onDestroy() {
        unregisterReceiver(mBroadcastListener);
        super.onDestroy();
    }

    private void refresh() {
        // refresh
    }

    private void update() {
        // update
    }

    private class BroadcastListener extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(Params.INTENT_REFRESH && !mIsActivityPaused)) {
                refresh();
            } else if (intent.getAction().equals(Params.INTENT_UPDATE)) {
                update();
            }
        }
    }
}

Ich möchte refresh()nur ausführen , wenn meine Aktivität auf dem Bildschirm sichtbar ist, aber ich möchte sie während der gesamten Lebensdauer der Aktivität abfangen INTENT_UPDATEund ausführen update(), unabhängig davon, ob die Aktivität sichtbar ist oder nicht.

Ich habe keine Möglichkeit gefunden, die Registrierung nur eines der beiden Filter aufzuheben, in denen ich mich registriere onCreate. Daher verwende ich ein Flag, um die Aktion zu aktivieren oder zu deaktivieren, die ausgeführt werden soll, wenn die INTENT_REFRESHSendung abgefangen wird, abhängig vom Status der Aktivität.

Die Frage ist : Ist das der richtige Ansatz?

Oder wäre es besser, zwei separate BroadcastReceiver wie folgt zu haben:

public class MyActivity extends Activity {
    private MyActivity.BroadcastListenerRefresh mBroadcastListenerRefresh;
    private MyActivity.BroadcastListenerUpdate mBroadcastListenerUpdate;
    private boolean mIsBroadcastListenerRefreshRegistered = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // Create the broadcast listeners
        mBroadcastListenerRefresh = new BroadcastListenerRefresh();
        mBroadcastListenerUpdate = new BroadcastListenerUpdate();

        registerReceiver(mBroadcastListenerRefresh, new IntentFilter(Params.INTENT_REFRESH));
        registerReceiver(mBroadcastListenerUpdate, new IntentFilter(Params.INTENT_UPDATE));
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mBroadcastListenerRefresh != null && !mIsBroadcastListenerRefreshRegistered) {
            registerReceiver(mBroadcastListenerRefresh, new IntentFilter(Params.INTENT_REFRESH));
            mIsBroadcastListenerRefreshRegistered = true;
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mBroadcastListenerRefresh != null && mIsBroadcastListenerRefreshRegistered) {
            unregisterReceiver(mBroadcastListenerRefresh);
            mIsBroadcastListenerRefreshRegistered = false;
        }
    }

    @Override
    protected void onDestroy() {
        unregisterReceiver(mBroadcastListenerRefresh);
        unregisterReceiver(mBroadcastListenerUpdate);
        super.onDestroy();
    }

    private void refresh() {
        // refresh
    }

    private void update() {
        // update
    }

    private class BroadcastListenerRefresh extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(Params.INTENT_REFRESH)) {
                refresh();
            }
        }
    }

    private class BroadcastListenerUpdate extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(Params.INTENT_UPDATE)) {
                update();
            }
        }
    }
}

Und welches hat eine bessere Leistung?

Lorenzo Polidori
quelle

Antworten:

210

Stattdessen können Sie zwei verschiedene Absichtsfilter bereitstellen:

Filter nur zur Aktualisierung

IntentFilter filterRefresh = new IntentFilter(Params.INTENT_REFRESH);

Filter für Aktualisierung und Aktualisierung

IntentFilter filterRefreshUpdate = new IntentFilter();
filterRefreshUpdate.addAction(Params.INTENT_REFRESH);
filterRefreshUpdate.addAction(Params.INTENT_UPDATE);

Jetzt können Sie zwischen Absichtsfiltern wechseln, indem Sie den gewünschten Filter registrieren und die Registrierung aufheben. Die Implementierung Ihres Empfängers ist jedoch dieselbe

Waqaslam
quelle
@Waqas Können Sie eine Beispielimplementierung des BroadcastReceiver bereitstellen, die mehrere Absichten erhalten würde? Ist es nur eine große Wenn-Dann-Sonst-Aussage?
Gonzobrains
2
@gonzobrains ja, für mehrere Absichten müssen Sie die gleiche Anzahl von if-else-Anweisungen verwenden, um sie herauszufiltern
waqaslam
@Waqas Gibt es eine Möglichkeit, dies dynamisch zu tun, sodass Sie einen generischen Rundfunkempfänger haben und ihm mehrere Handler hinzufügen können, damit Sie das grundlegende Framework nicht jedes Mal ändern müssen, wenn Sie ihm eine neue Absicht hinzufügen?
Gonzobrains
Was genau meinst du mit "dynamisch machen" ? Fügen Sie einfach alle Aktionszeichenfolgen in Ihre Absichtsfilter ein und führen Sie if-else aus, um die erforderlichen Aktionszeichenfolgen zu identifizieren.
Waqaslam
3
Ich verstehe nicht alle positiven Stimmen für diese Antwort. Für das, was die Operation versucht hat, scheint 1 Absichtsfilter mit 2 Aktionen angemessen zu sein. Der Code im ersten Codeblock in der Frage scheint alles zu sein, was benötigt wird.
hBrent
28

Erstellen Sie für jede Aktion IntentFilter und registrieren Sie es.

@Override
protected void onResume() {

    super.onResume();

    BroadcastListener receiver = new BroadcastListener();

    // Register the filter for listening broadcast.
    IntentFilter filterRefresh = new IntentFilter(Params.INTENT_REFRESH);
    IntentFilter filterUpdate = new IntentFilter(Params.INTENT_UPDATE);

    registerReceiver(receiver, filterRefresh);
    registerReceiver(receiver, filterUpdate);
} 



private class BroadcastListener extends BroadcastReceiver {
    public void onReceive(Context ctx, Intent intent) {

        if (intent.getAction().equals(Params.INTENT_UPDATE)) {
            update();
        } else if(intent.getAction().equals(Params.INTENT_REFRESH)) {
            refresh();
        }
    }

}
Pawan Yadav
quelle
4
Sollte ich mir keine Sorgen machen, registerReceivermehrmals anzurufen und nur einmal aufzurufen unregisterReceiver?
Mr5 5.
3
Wenn Sie registerReceiver mehrmals aufrufen und unregisterReceiver nur einmal aufheben, kann die vorherige Instanz des Empfängers auslaufen. Die Instanz registriert sich dann und verwendet diese Instanz zum Aufheben der Registrierung.
Pawan Yadav
2
Wenn Sie sich mehrmals für dieselbe Aktion registrieren würden, würden Sie sich Sorgen machen.
Stdout
1
Sollte dies nicht entmutigt werden? Für Google-Entwickler wäre es hilfreich, eine Ausnahme auszulösen, wenn Sie denselben BroadcastReceiver mehrmals registrieren. Stattdessen sollten wir dem Absichtsfilter mehrere Aktionen hinzufügen.
TheRealChx101