BroadcastReceiver dengan beberapa filter atau beberapa BroadcastReceivers?

115

Saya memiliki Aktivitas Android yang perlu menangkap dua siaran berbeda. Pendekatan saya saat ini adalah memiliki satu BroadcastReceiverdalam Aktivitas dan menangkap kedua siaran dengannya:

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

Saya ingin mengeksekusi refresh()hanya jika Aktivitas saya terlihat di layar, tetapi saya ingin menangkap INTENT_UPDATEdan mengeksekusi update()selama seluruh masa Aktivitas, terlepas dari apakah Aktivitas tersebut terlihat atau tidak.

Saya tidak menemukan cara apa pun untuk membatalkan pendaftaran hanya satu dari dua filter yang saya daftarkan onCreate, jadi saya menggunakan bendera untuk mengaktifkan atau menonaktifkan tindakan yang akan dijalankan saat INTENT_REFRESHsiaran ditangkap, tergantung pada status Aktivitas.

Pertanyaannya adalah : apakah ini pendekatan yang benar?

Atau, apakah lebih baik memiliki dua BroadcastReceivers terpisah sebagai berikut:

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

Dan mana yang kinerjanya lebih baik?

Lorenzo Polidori
sumber

Jawaban:

210

sebagai gantinya, Anda dapat memberikan dua filter maksud yang berbeda:

filter untuk penyegaran saja

IntentFilter filterRefresh = new IntentFilter(Params.INTENT_REFRESH);

filter untuk menyegarkan dan memperbarui

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

sekarang Anda dapat beralih di antara filter maksud dengan mendaftarkan dan membatalkan pendaftaran yang diinginkan tetapi penerapan penerima Anda akan sama

waqaslam
sumber
@Waqas Dapatkah Anda memberikan contoh implementasi BroadcastReceiver yang akan menerima banyak maksud? Apakah itu hanya pernyataan jika-maka-lain yang besar?
gonzobrains
2
@gonzobrains ya, untuk maksud ganda Anda perlu menggunakan jumlah yang sama dari pernyataan if-else untuk memfilternya
waqaslam
@Waqas Adakah cara untuk melakukan ini secara dinamis sehingga Anda memiliki penerima siaran umum dan dapat menambahkan beberapa penangan ke dalamnya sehingga tidak perlu mengubah kerangka dasar setiap kali Anda menambahkan maksud baru?
gonzobrains
apa yang sebenarnya Anda maksud dengan "melakukan ini secara dinamis" ? Cukup sertakan semua string tindakan di dalam filter maksud Anda dan lakukan if-else untuk mengidentifikasi string tindakan yang Anda perlukan.
waqaslam
3
Saya tidak mengerti semua suara positif untuk jawaban ini. Untuk apa yang op coba lakukan, tampaknya 1 filter maksud dengan 2 tindakan sudah cukup. Kode di blok kode pertama dalam pertanyaan tampaknya satu-satunya yang dibutuhkan.
hBrent
28

Untuk setiap tindakan, buat IntentFilter dan daftarkan.

@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
sumber
4
Bukankah saya harus khawatir menelepon registerReceiverberkali-kali dan hanya memanggil unregisterReceiversatu kali?
mr5
3
Jika Anda memanggil registerReceiver beberapa kali dan unregisterReceiver hanya satu kali, maka instance receiver sebelumnya mungkin bocor. Jadi contoh u mendaftar kemudian menggunakan contoh itu untuk unregister.
Pawan Yadav
2
Jika Anda mendaftar beberapa kali untuk tindakan yang sama, maka menurut saya Anda harus khawatir.
stdout
1
Bukankah ini harus dikecilkan? Akan sangat membantu bagi pengembang Google untuk membuat pengecualian saat Anda mendaftarkan BroadcastReceiver yang sama lebih dari sekali. Sebagai gantinya, kita harus menambahkan beberapa tindakan ke filter maksud.
TheRealChx101