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.