BroadcastReceiver con più filtri o più BroadcastReceiver?


115

Ho un'attività Android che deve catturare due diverse trasmissioni. Il mio approccio attuale è quello di avere un singolo BroadcastReceiverall'interno dell'attività e catturare entrambe le trasmissioni con esso:

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

Voglio eseguire refresh()solo se la mia attività è visibile sullo schermo, ma voglio catturare INTENT_UPDATEed eseguire update()durante l'intera durata dell'attività, indipendentemente dal fatto che l'attività sia visibile o meno.

Non ho trovato alcun modo per annullare la registrazione solo di uno dei due filtri in cui mi registro onCreate, quindi utilizzo un flag per abilitare o disabilitare l'azione da eseguire quando la INTENT_REFRESHtrasmissione viene catturata, a seconda dello stato dell'attività.

La domanda è : è questo l'approccio corretto?

Oppure, sarebbe meglio avere due BroadcastReceiver separati come segue:

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

E quale ha prestazioni migliori?

Risposte:


210

invece, puoi fornire due diversi filtri di intenti:

filtro solo per l'aggiornamento

IntentFilter filterRefresh = new IntentFilter(Params.INTENT_REFRESH);

filtro per aggiornamento e aggiornamento

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

ora puoi passare da un filtro di intenti registrando e annullando la registrazione di quello desiderato ma l'implementazione del tuo ricevitore sarebbe la stessa


@Waqas Potete fornire un'implementazione di esempio del BroadcastReceiver che riceverebbe più intenti? È solo una grande affermazione if-then-else?
— gonzobrains

2
@gonzobrains sì, per più intenti è necessario utilizzare lo stesso numero di istruzioni if-else per filtrarli
— waqaslam

@Waqas Esiste un modo per farlo dinamicamente in modo da avere un ricevitore di trasmissione generico e poter aggiungere più gestori ad esso in modo da non dover modificare il framework di base ogni volta che si aggiunge un nuovo intento?
— gonzobrains

cosa intendi esattamente con "farlo dinamicamente" ? Includere semplicemente tutte le stringhe di azione all'interno dei filtri di intento ed eseguire if-else per identificare le stringhe di azione richieste.
— waqaslam

3
Non capisco tutti i voti positivi per questa risposta. Per quello che l'operazione stava cercando di fare, sembra che 1 filtro di intento con 2 azioni sia adeguato. Il codice nel primo blocco di codice nella domanda sembra essere tutto ciò che serve.
— hBrent

28

Per ogni azione, crea IntentFilter e registralo.

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

}

4
Non dovrei preoccuparmi di chiamare registerReceiverpiù volte e di invocare unregisterReceiveruna sola volta?
— mr5

3
Se chiami registerReceiver più volte e unregisterReceiver solo una volta, l'istanza precedente del ricevitore potrebbe perdere. Quindi l'istanza si registra quindi utilizzando quell'istanza per annullare la registrazione.
— Pawan Yadav

2
Se dovessi registrarti più volte per la stessa azione, direi che dovresti essere preoccupato.
— stdout

1
Non dovrebbe essere scoraggiato? Sarebbe utile per gli sviluppatori di Google lanciare un'eccezione quando registri lo stesso BroadcastReceiver più di una volta. Dovremmo invece aggiungere più azioni al filtro intento.
— TheRealChx101
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.