BroadcastReceiver z wieloma filtrami lub wieloma BroadcastReceiver?


115

Mam działanie na Androida, które musi przechwytywać dwie różne transmisje. Moje obecne podejście polega na tym, aby mieć singiel BroadcastReceiverw ramach działania i złapać za jego pomocą obie transmisje:

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

Chcę wykonać refresh()tylko wtedy, gdy moje działanie jest widoczne na ekranie, ale chcę je przechwycić INTENT_UPDATEi wykonać update()przez cały czas jego trwania, niezależnie od tego, czy działanie jest widoczne, czy nie.

Nie znalazłem sposobu na wyrejestrowanie tylko jednego z dwóch filtrów, w których się rejestruję onCreate, więc używam flagi, aby włączyć lub wyłączyć akcję, która ma być wykonana po przechwyceniu INTENT_REFRESHtransmisji, w zależności od stanu działania.

Pytanie brzmi : czy to jest właściwe podejście?

A może lepiej byłoby mieć dwa oddzielne odbiorniki BroadcastReceivers w następujący sposób:

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

A który z nich ma lepszą wydajność?

Odpowiedzi:


210

zamiast tego możesz podać dwa różne filtry intencji:

filtr tylko do odświeżenia

IntentFilter filterRefresh = new IntentFilter(Params.INTENT_REFRESH);

filtr do odświeżania i aktualizacji

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

teraz możesz przełączać się między filtrami intencji, rejestrując i wyrejestrowując żądany, ale implementacja twojego odbiorcy byłaby taka sama


@Waqas Czy możesz podać przykładową implementację BroadcastReceiver, która otrzymałaby wiele intencji? Czy to tylko duże stwierdzenie „jeśli-to-jeszcze”?
— gonzobrains

2
@gonzobrains tak, w przypadku wielu zamiarów musisz użyć równej liczby instrukcji if-else, aby je odfiltrować
— waqaslam

@Waqas Czy istnieje sposób, aby zrobić to dynamicznie, aby mieć ogólny odbiornik rozgłoszeniowy i dodać do niego wiele programów obsługi, aby nie musieć modyfikować podstawowego szkieletu za każdym razem, gdy dodajesz do niego nową intencję?
— gonzobrains

co dokładnie masz na myśli, mówiąc „robić to dynamicznie” ? Po prostu umieść wszystkie ciągi akcji wewnątrz swoich filtrów intencji i wykonaj if-else, aby zidentyfikować wymagane ciągi akcji.
— waqaslam

3
Nie rozumiem wszystkich głosów za tą odpowiedzią. Wydaje się, że do tego, co próbował zrobić operator, wystarczy 1 filtr intencji z 2 akcjami. Kod z pierwszego bloku kodu w pytaniu wydaje się być wszystkim, czego potrzeba.
— hBrent,

28

Dla każdej akcji utwórz IntentFilter i zarejestruj go.

@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
Czy nie powinienem się martwić, dzwoniąc registerReceiverkilka razy i wywołując unregisterReceivertylko jeden raz?
— mr5

3
Jeśli u call registerReceiver wielokrotnie i unregisterReceiver tylko raz, to poprzednia instancja odbiornika może przeciekać. Więc instancja u rejestruje się, a następnie używa tej instancji do wyrejestrowania.
— Pawan Yadav,

2
Gdybyś miał rejestrować się wiele razy na tę samą akcję, powiedziałbym, że powinieneś się martwić.
— wyjście

1
Nie należy tego zniechęcać? Byłoby pomocne dla programistów Google, aby zgłosić wyjątek, gdy rejestrujesz ten sam BroadcastReceiver więcej niż raz. Zamiast tego powinniśmy dodać wiele akcji do filtra intencji.
— TheRealChx101
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.