BroadcastReceiver с несколькими фильтрами или несколькими BroadcastReceiver?

115

У меня есть Android Activity, которому нужно поймать две разные трансляции. Мой текущий подход состоит в том, чтобы иметь сингл BroadcastReceiverв Activity и ловить с ним обе трансляции:

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перехвате трансляции, в зависимости от состояния Activity.

Вопрос в том, правильный ли это подход?

Или было бы лучше иметь два отдельных BroadcastReceiver следующим образом:

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

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

waqaslam
источник
@Waqas Можете ли вы предоставить пример реализации BroadcastReceiver, который будет принимать несколько намерений? Это просто большое утверждение «если-то-еще»?
gonzobrains 08
2
@gonzobrains да, для нескольких целей вам нужно использовать равное количество операторов if-else, чтобы отфильтровать их
waqaslam
@Waqas Есть ли способ сделать это динамически, чтобы у вас был общий широковещательный приемник и можно было добавить к нему несколько обработчиков, чтобы не изменять базовую структуру каждый раз, когда вы добавляете в нее новое намерение?
gonzobrains 08
что именно вы имеете в виду под «делать это динамически» ? Просто включите все строки действий в свои фильтры намерений и выполните if-else, чтобы определить требуемые строки действий.
Вакаслам
3
Я не понимаю всех голосов за этот ответ. Для того, что пытался сделать оператор, кажется, что достаточно 1 фильтра намерений с 2 ​​действиями. Код в первом блоке кода в вопросе кажется всем, что нужно.
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
Если вы вызываете registerReceiver несколько раз, а unregisterReceiver только один раз, то предыдущий экземпляр получателя может просочиться. Таким образом, экземпляр u регистрируется, а затем использует этот экземпляр для отмены регистрации.
Паван Ядав
2
Если бы вам пришлось регистрироваться несколько раз на одно и то же действие, я бы сказал, что вам следует беспокоиться.
stdout
1
Разве это не следует обескураживать? Разработчикам Google было бы полезно генерировать исключение, если вы регистрируете один и тот же BroadcastReceiver более одного раза. Вместо этого мы должны добавить несколько действий в фильтр намерений.
TheRealChx101