BroadcastReceiver з декількома фільтрами або декількома BroadcastReceivers?


115

У мене є Android Активність, яка потребує перегляду двох різних передач. Мій сучасний підхід полягає в тому, щоб створити сингл BroadcastReceiverв рамках діяльності та охопити обидва ефіри разом із ним:

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

Я хочу виконати refresh()лише в тому випадку, якщо мою активність видно на екрані, але я хочу зафіксувати INTENT_UPDATEта виконати update()протягом усього періоду дії, незалежно від того, видимість діяльності чи ні.

Я не знайшов жодного способу відреєстрації лише одного з двох фільтрів, в яких я реєструюсь onCreate, тому я використовую прапор, щоб увімкнути або вимкнути дію, яку слід виконати, коли INTENT_REFRESHтрансляція перехоплена, залежно від стану активності.

Питання : чи це правильний підхід?

Або краще було б мати два окремі широкомовні приймачі:

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

І хто з них має кращі показники?

Відповіді:


210

натомість ви можете надати два різні фільтри намірів:

фільтр лише для оновлення

IntentFilter filterRefresh = new IntentFilter(Params.INTENT_REFRESH);

фільтр для оновлення та оновлення

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

тепер ви можете переходити між фільтрами намірів, зареєструвавши та скасувавши потрібний, але реалізація вашого приймача була б такою ж


@Waqas Чи можете ви навести приклад реалізації програми BroadcastReceiver, яка отримала б кілька намірів? Це просто велика заява якщо тоді?
гонзобраїни

2
@gonzobrains так, для кількох намірів вам потрібно використовувати рівну кількість тверджень if-else, щоб їх відфільтрувати
waqaslam

@Waqas Чи існує спосіб зробити це динамічно, щоб у вас був загальний приймач широкомовної передачі і можна було додати до нього кілька обробників, щоб не довелося змінювати базовий фреймворк кожного разу, коли ви додаєте до нього новий намір?
гонзобраїни

що саме ви маєте на увазі під "робити це динамічно" ? Просто включіть всі рядки дій всередині ваших фільтрів намірів і виконайте if-else, щоб визначити потрібні рядки дій.
waqaslam

3
Я не розумію всіх прихильників цієї відповіді. Для того, що ОП намагалася зробити, здається, що 1 фільтр намірів з двома діями є достатнім. Код у першому блоці коду у питанні, здається, є всім необхідним.
hBrent

28

Для кожної дії створіть IntentFilter та зареєструйте її.

@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
Чи не повинен я турбуватися, коли я дзвонив registerReceiverкілька разів і unregisterReceiverлише один раз викликав ?
mr5

3
Якщо u виклику registerReceiver декілька разів, а undegisterReceiver лише один раз, тоді попередній екземпляр приймача може просочитися. Отже, реєстратор u реєструється, використовуючи цей примірник для реєстрації.
Pawan Yadav

2
Якщо ви реєструвались кілька разів на одній дії, то я б сказав, що ви повинні турбуватися.
stdout

1
Чи не слід це зневажати? Google-розробникам було б корисно кинути виняток, коли ви реєструєте той самий BroadcastReceiver не один раз. Натомість слід додати декілька дій до фільтру намірів.
TheRealChx101
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.