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.