BroadcastReceiver con múltiples filtros o múltiples BroadcastReceivers?

115

Tengo una actividad de Android que necesita capturar dos transmisiones diferentes. Mi enfoque actual es tener uno BroadcastReceiverdentro de la Actividad y capturar ambas transmisiones con él:

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

Quiero ejecutar refresh()solo si mi Actividad está visible en la pantalla, pero quiero capturar INTENT_UPDATEy ejecutar update()durante toda la vida útil de la Actividad, independientemente de si la Actividad es visible o no.

No encontré ninguna forma de anular el registro de solo uno de los dos filtros en los que me registro onCreate, por lo que uso una bandera para habilitar o deshabilitar la acción que se ejecutará cuando se capture la INTENT_REFRESHtransmisión, según el estado de la actividad.

La pregunta es : ¿es este el enfoque correcto?

O sería mejor tener dos BroadcastReceivers separados de la siguiente manera:

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

¿Y cuál tiene mejor rendimiento?

Lorenzo Polidori
fuente

Respuestas:

210

en su lugar, puede proporcionar dos filtros de intención diferentes:

filtrar solo para actualizar

IntentFilter filterRefresh = new IntentFilter(Params.INTENT_REFRESH);

filtro para actualizar y actualizar

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

ahora puede cambiar entre filtros de intención registrando y anulando el registro del deseado, pero la implementación de su receptor sería la misma

waqaslam
fuente
@Waqas ¿Puede proporcionar una implementación de ejemplo del BroadcastReceiver que recibiría múltiples intenciones? ¿Es solo una gran declaración si-entonces-si no?
Gonzobrains
2
@gonzobrains sí, para múltiples intenciones, debe usar el mismo número de declaraciones if-else para filtrarlas
waqaslam
@Waqas ¿Hay alguna manera de hacer esto dinámicamente para que tenga un receptor de transmisión genérico y pueda agregarle múltiples controladores para no tener que modificar el marco básico cada vez que agrega una nueva intención?
gonzobrains
¿Qué quiere decir exactamente con "hacer esto dinámicamente" ? Simplemente incluya todas las cadenas de acción dentro de sus filtros de intención y realice if-else para identificar las cadenas de acción necesarias.
waqaslam
3
No entiendo todos los votos a favor de esta respuesta. Por lo que la operación estaba tratando de hacer, parece que 1 filtro de intención con 2 acciones es adecuado. El código del primer bloque de código de la pregunta parece ser todo lo que se necesita.
hBrent
28

Para cada acción, cree IntentFilter y regístrelo.

@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
fuente
4
¿No debería preocuparme llamar registerReceivervarias veces e invocar unregisterReceiversolo una vez?
mr5
3
Si llama a registerReceiver varias veces y unregisterReceiver solo una vez, la instancia anterior del receptor podría tener fugas. Entonces, la instancia u registra luego usa esa instancia para anular el registro.
Pawan Yadav
2
Si se registrara varias veces en la misma acción, diría que debería preocuparse.
salida
1
¿No debería desalentarse esto? Sería útil para los desarrolladores de Google lanzar una excepción cuando registra el mismo BroadcastReceiver más de una vez. En su lugar, deberíamos agregar varias acciones al filtro de intención.
TheRealChx101