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ออกอากาศถูกจับได้ทั้งนี้ขึ้นอยู่กับสถานะของกิจกรรม

คำถามคือนี่เป็นแนวทางที่ถูกต้องหรือไม่?

หรือจะดีกว่าไหมหากมี BroadcastReceivers สองตัวแยกกันดังนี้:

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 ที่จะได้รับหลาย Intent ได้หรือไม่? มันเป็นเพียงคำสั่ง if-then-else ที่ยิ่งใหญ่?
gonzobrains

2
@gonzobrains ใช่สำหรับหลาย Intent คุณต้องใช้ if-else จำนวนเท่ากันเพื่อกรองออก
waqaslam

@Waqas มีวิธีดำเนินการแบบไดนามิกเพื่อให้คุณมีเครื่องรับสัญญาณออกอากาศทั่วไปและสามารถเพิ่มตัวจัดการหลายตัวเพื่อไม่ต้องแก้ไขกรอบงานพื้นฐานทุกครั้งที่คุณเพิ่มจุดประสงค์ใหม่หรือไม่
gonzobrains

"การทำแบบไดนามิก"หมายความว่าอย่างไร เพียงรวมสตริงการดำเนินการทั้งหมดไว้ในตัวกรองความตั้งใจของคุณและดำเนินการ if-else เพื่อระบุสตริงการดำเนินการที่คุณต้องการ
waqaslam

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
หากคุณโทรลงทะเบียนรับหลายครั้งและยกเลิกการลงทะเบียนรับเพียงครั้งเดียวอินสแตนซ์ของผู้รับก่อนหน้านี้อาจรั่วไหล ดังนั้นอินสแตนซ์ที่คุณลงทะเบียนจากนั้นใช้อินสแตนซ์นั้นเพื่อยกเลิกการลงทะเบียน
Pawan Yadav

2
หากคุณต้องลงทะเบียนหลายครั้งในการกระทำเดียวกันฉันว่าคุณน่าจะกังวล
stdout

1
นี่ไม่ควรท้อแท้หรือ? จะเป็นประโยชน์สำหรับนักพัฒนา Google ที่จะทิ้งข้อยกเว้นเมื่อคุณลงทะเบียน BroadcastReceiver เดียวกันมากกว่าหนึ่งครั้ง แต่เราควรเพิ่มการดำเนินการหลายรายการในตัวกรองความตั้งใจ
TheRealChx101
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.