วิธีใช้ LocalBroadcastManager


452

วิธีการใช้งาน / หาLocalBroadcastManagerตามที่อธิบายไว้ในเอกสาร Googleและบริการออกอากาศ doc ?

ฉันลอง google แล้ว แต่ไม่มีรหัสให้เริ่มด้วย?

เอกสารบอกว่าฉันควรใช้มันหากฉันต้องการออกอากาศภายในกระบวนการแอพของฉัน แต่ฉันไม่รู้ว่าจะหาได้จากที่ไหน

ความช่วยเหลือ / ความคิดเห็นใด ๆ

อัปเดต : ฉันรู้วิธีใช้การออกอากาศ แต่ไม่ทราบวิธีการให้LocalBroadcastManagerบริการในโครงการของฉัน


อีกครั้งคุณได้ลงทะเบียนผู้รับในรายการ ถ้าใช่โปรดแจ้งให้เราทราบได้อย่างไร
Mudassir

2
ฉันไม่คิดว่าคุณจะต้องลงทะเบียนผู้รับสำหรับการออกอากาศดังกล่าวในรายการเพราะถ้าคุณทำแล้วผู้รับนั้นจะรับฟังการออกอากาศทั่วโลก
waqaslam

2
จริง จากนั้นหมายความว่าฉันต้องทำมันในรหัสตามที่ระบุในคำตอบด้านล่าง; LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, new IntentFilter("custom-event-name"));
Mudassir

2
LocalBroadcastManagerเลิกใช้แล้ว ฉันแทนที่ฉันด้วยไลบรารี EventBus ซึ่งดีกว่ามาก IMO
Kris B

คำตอบ:


862

ฉันจะตอบคำถามนี้ต่อไป ในกรณีที่มีคนต้องการมัน

ReceiverActivity.java

"custom-event-name"กิจกรรมที่นาฬิกาสำหรับการแจ้งเตือนสำหรับเหตุการณ์ที่มีชื่อ

@Override
public void onCreate(Bundle savedInstanceState) {

  ...

  // Register to receive messages.
  // We are registering an observer (mMessageReceiver) to receive Intents
  // with actions named "custom-event-name".
  LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,
      new IntentFilter("custom-event-name"));
}

// Our handler for received Intents. This will be called whenever an Intent
// with an action named "custom-event-name" is broadcasted.
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {
    // Get extra data included in the Intent
    String message = intent.getStringExtra("message");
    Log.d("receiver", "Got message: " + message);
  }
};

@Override
protected void onDestroy() {
  // Unregister since the activity is about to be closed.
  LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
  super.onDestroy();
}

SenderActivity.java

กิจกรรมที่สองที่ส่ง / ออกอากาศการแจ้งเตือน

@Override
public void onCreate(Bundle savedInstanceState) {

  ...

  // Every time a button is clicked, we want to broadcast a notification.
  findViewById(R.id.button_send).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
      sendMessage();
    }
  });
}

// Send an Intent with an action named "custom-event-name". The Intent sent should 
// be received by the ReceiverActivity.
private void sendMessage() {
  Log.d("sender", "Broadcasting message");
  Intent intent = new Intent("custom-event-name");
  // You can also include some extra data.
  intent.putExtra("message", "This is my message!");
  LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}

ด้วยโค้ดข้างต้นทุกครั้งที่ปุ่มR.id.button_sendมีการคลิกเจตจำนงออกอากาศและได้รับโดยในmMessageReceiverReceiverActivity

ผลลัพธ์การดีบักควรมีลักษณะดังนี้:

01-16 10:35:42.413: D/sender(356): Broadcasting message
01-16 10:35:42.421: D/receiver(356): Got message: This is my message! 

7
ขอบคุณ ทำงานได้แล้ว แต่ปัญหาที่ฉันเผชิญคือการหยุดเรียนใน LocalBroadcastManager ตั้งแต่คลาสแพ็กเกจการสนับสนุนดังนั้นฉันจึงไม่สามารถใช้งานได้ในแพ็คเกจปกติจนกระทั่งฉันเพิ่มไลบรารีความเข้ากันได้จากเครื่องมือ Android เมื่อเพิ่มแล้วทุกอย่างก็โอเค อย่างไรก็ตามขอบคุณสำหรับคำตอบ
waqaslam

195
โปรดทราบว่าonDestroy()ไม่รับประกันว่าจะถูกเรียก !!! คุณต้องใช้onPause()(เพราะonPause()มีการรับประกันเท่านั้น) และonResume()(เพราะมันเหมาะกับonPause())
18446744073709551615

5
โปรดทราบว่าสิ่งที่ google เอกสารตอนนี้พูดเกี่ยวกับกิจกรรมหลังจาก onPause (): Killable = Pre-HONEYCOMB เริ่มต้นด้วย Honeycomb แอปพลิเคชันไม่ได้อยู่ในสถานะที่สามารถฆ่าได้จนกว่า onStop () จะกลับมา
18446744073709551615

59
onDestroy()ไม่มีปัญหา กรณีที่ไม่มีการเรียกใช้คือเมื่อแอพถูกฆ่าและไม่สำคัญว่าคุณจะไม่ถอนการลงทะเบียนในกรณีนั้นเนื่องจากไม่มีแม้แต่รายชื่อผู้รับที่ยังมีชีวิตอยู่
zapl

4
@Selvin ฉันหวังว่าคุณจะรู้ว่าคุณสามารถทำให้ BroadcastReciever ได้อ้างอิงอย่างอ่อน ๆ กับกิจกรรมที่ได้รับและทำให้มันยกเลิกการลงทะเบียนถ้ามันถูกกำพร้า คุณไม่จำเป็นต้องยกเลิกการลงทะเบียนใน onPause, onDestroy นั้นใช้ได้ตราบใดที่คุณไม่ได้ใช้ BroadcastReceiver เพื่อให้กิจกรรมของคุณอยู่ใน RAM ตัวอย่างของคุณแสดงให้เห็นถึงแนวปฏิบัติที่ไม่ดีกับคลาสภายในที่รั่วออกมาคือคลาสภายนอกไม่ใช่เฉพาะของ BroadcastReceiver และเป็นสิ่งที่โปรแกรมเมอร์ต้องป้องกันเสมอ สำหรับการแก้ไข GUI คุณสามารถจัดเก็บสถานะเมื่อกิจกรรมดำเนินต่อคุณไม่ต้องแก้ไข GUI
JohanShogun

133

ฉันต้องการที่จะตอบอย่างครอบคลุม

  1. LocalbroadcastManager รวมอยู่ใน android 3.0 ขึ้นไปดังนั้นคุณต้องใช้ไลบรารีการสนับสนุน v4 สำหรับการเปิดตัวครั้งแรก ดูคำแนะนำได้ ที่นี่

  2. สร้างเครื่องรับสัญญาณออกอากาศ:

    private BroadcastReceiver onNotice= new BroadcastReceiver() {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            // intent can contain anydata
            Log.d("sohail","onReceive called");
            tv.setText("Broadcast received !");
    
        }
    };
  3. ลงทะเบียนผู้รับของคุณในกิจกรรมที่ชอบ:

    protected void onResume() {
            super.onResume();
    
            IntentFilter iff= new IntentFilter(MyIntentService.ACTION);
            LocalBroadcastManager.getInstance(this).registerReceiver(onNotice, iff);
        }
    
    //MyIntentService.ACTION is just a public static string defined in MyIntentService.
  4. ถอนการลงทะเบียนผู้รับใน onPause:

    protected void onPause() {
      super.onPause();
      LocalBroadcastManager.getInstance(this).unregisterReceiver(onNotice);
    }
  5. ตอนนี้เมื่อใดก็ตามที่ส่งการออกอากาศจากแอพพลิเคชั่นของท้องถิ่นแอพพลิเคชั่น onReceive ของ onNotice จะถูกเรียก :)

แก้ไข: คุณสามารถอ่านบทแนะนำฉบับสมบูรณ์ได้ที่นี่LocalBroadcastManager: ส่งข้อความภายในแอปพลิเคชัน


15
+1 หาก Broadcast Receiver ของคุณอยู่ในส่วนให้ลงทะเบียนโดยใช้LocalBroadcastManager.getInstance(getActivity()).registerReceiver(onNotice);และยกเลิกการลงทะเบียนโดยใช้LocalBroadcastManager.getInstance(getActivity()).unregisterReceiver(onNotice);
PeteH

3
คุณแน่ใจหรือว่า LocalBroadcastManager รวมอยู่ใน Android 3.0 ขึ้นไป ไม่พบที่ใดก็ได้ยกเว้นการสนับสนุน lib
mente

5
น่าแปลกที่ LBM จะรวมอยู่ในห้องสมุดสนับสนุนเท่านั้น
Jeffrey Blattman

1
super.onPause () ควรเป็นคำสั่งสุดท้ายเมื่อเขียนทับวิธี onPause ยกเลิกการลงทะเบียนก่อน super.on
หยุดชั่วคราว

2
ฉันเชื่อว่าคุณอาจต้องการย้ายวงจรชีวิตของคุณไปonStopเพราะใน Android API 24+ ด้วย“ Multi-Window / Split-View” (เปิดใช้งานตามค่าเริ่มต้นบน API 26+ affaicr) กิจกรรมที่ไม่ได้มีการโต้ตอบนั้นอยู่ในสถานะหยุดชั่วคราว ที่มา: developer.android.com/guide/topics/ui/…
Martin Marconcini

45

เมื่อสิ้นสุดการรับ:

  • ลงทะเบียน LocalBroadcast Receiver ก่อน
  • จากนั้นจัดการข้อมูลเจตนาเข้ามาใน onReceive

      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
    
          LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this);
          lbm.registerReceiver(receiver, new IntentFilter("filter_string"));
      }
    
      public BroadcastReceiver receiver = new BroadcastReceiver() {
          @Override
          public void onReceive(Context context, Intent intent) {
              if (intent != null) {
                  String str = intent.getStringExtra("key");
                  // get all your data from intent and do what you want 
              }
          }
      };

ในการส่งที่สิ้นสุด:

   Intent intent = new Intent("filter_string");
   intent.putExtra("key", "My Data");
   // put your all data using put extra 

   LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

ในกรณีของฉันเฉพาะเมื่อฉันตั้งค่าการกระทำโดยเจตนาเมื่อส่งงานออกอากาศเป็นอย่างอื่นวิธี onReceive () ไม่เคยเรียก ...
Akash Bisariya

27

ใน Eclipse ในที่สุดฉันก็ต้องเพิ่มCompatibility / Support Libraryโดยการคลิกขวาที่โครงการของฉันและเลือก:

Android Tools -> Add Support Library

เมื่อมันถูกเพิ่มเข้ามาฉันก็สามารถใช้LocalBroadcastManagerคลาสในโค้ดของฉันได้


ห้องสมุดที่เข้ากันได้กับ Android


13

localbroadcastmanager เลิกใช้งานใช้รูปแบบที่สังเกตได้แทน

androidx.localbroadcastmanager กำลังเลิกใช้ในรุ่น 1.1.0

เหตุผล

LocalBroadcastManagerเป็นบัสเหตุการณ์ทั่วทั้งแอปพลิเคชันและรวบรวมการละเมิดเลเยอร์ในแอปของคุณ องค์ประกอบใด ๆ อาจฟังเหตุการณ์จากองค์ประกอบอื่น ๆ มันสืบทอดข้อ จำกัด กรณีการใช้งานที่ไม่จำเป็นของระบบ BroadcastManager นักพัฒนาจะต้องใช้ Intent แม้ว่าวัตถุจะมีชีวิตอยู่ในกระบวนการเดียวเท่านั้นและจะไม่ทิ้งมันไว้ ด้วยเหตุผลเดียวกันนี้ไม่ได้ติดตาม BroadcastManager ที่ชาญฉลาด

สิ่งเหล่านี้ช่วยเสริมประสบการณ์นักพัฒนาที่สับสน

การแทนที่

คุณสามารถแทนที่การใช้งานLocalBroadcastManagerด้วยการใช้งานอื่น ๆ ของรูปแบบที่สังเกตได้ ตัวเลือกที่เหมาะสมอาจเป็นLiveDataหรือสตรีมปฏิกิริยา

ข้อได้เปรียบของ LiveData

คุณสามารถขยายLiveDataวัตถุโดยใช้รูปแบบซิงเกิลเพื่อห่อบริการระบบเพื่อให้สามารถใช้ร่วมกันในแอปของคุณ LiveDataวัตถุเชื่อมต่อกับระบบการให้บริการครั้งเดียวแล้วสังเกตการณ์ที่ต้องการทรัพยากรเพียงสามารถชมLiveDataวัตถุ

 public class MyFragment extends Fragment {
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        LiveData<BigDecimal> myPriceListener = ...;
        myPriceListener.observe(this, price -> {
            // Update the UI.
        });
    }
}

observe()วิธีผ่านชิ้นส่วนซึ่งเป็นตัวอย่างของการLifecycleOwnerเป็นอาร์กิวเมนต์แรก การทำเช่นนี้แสดงว่าผู้สังเกตการณ์นี้ถูกผูกไว้กับLifecycleวัตถุที่เกี่ยวข้องกับเจ้าของความหมาย:

  • หากวัตถุวัฏจักรไม่อยู่ในสถานะใช้งานผู้สังเกตการณ์จะไม่ถูกเรียกใช้แม้ว่าค่าจะเปลี่ยนแปลง

  • หลังจากวัตถุระยะเวลาการทำงานถูกทำลายผู้สังเกตการณ์จะถูกลบโดยอัตโนมัติ

ความจริงที่ว่าอLiveDataอบเจ็กต์นั้นตระหนักถึงวงจรชีวิตซึ่งหมายความว่าคุณสามารถแชร์สิ่งเหล่านี้ระหว่างกิจกรรมชิ้นส่วนและบริการ


1
คุณมีความถูกต้องเกี่ยวกับการรั่วไหลของบริบทไปทั่วโลก แต่ฉันต้องการที่จะรู้ว่าสิ่งที่จะทดแทนที่เหมาะสมเมื่อฉันต้องการที่จะสื่อสารจากบริการเบื้องหน้าที่ทำงานแม้ไม่มีกิจกรรม แต่เมื่อกิจกรรมมาพวกเขาต้องสื่อสาร?
ateebahmed

2
สร้างคลาสเดี่ยวด้วยวัตถุ LiveData และโพสต์ข้อมูลของคุณจากบริการ เมื่อกิจกรรมเปิดตัวกิจกรรมสามารถสังเกต LiveData ได้อย่างง่ายดายโดยไม่มีอันตรายใด ๆ เช่น: MyServiceData.getInstance (). getMyData (). สังเกต ...
ดาริส

3
ฉันจะคิดถึง LocalBroadcastManager ถ้ามันสับสนกับนักพัฒนาซอฟต์แวร์ของ Google บางทีพวกเขาจำเป็นต้องหยุดเรื่องวิศวกรรมมากเกินไป?
AFD

@Darish คลาสเดียวนี้จะเทียบเท่ากับการเก็บไว้ใน Application Object หรือไม่? เหตุใดสถานะระดับโลกเช่นนี้ในกรณีเหล่านี้จึงไม่ถือว่าเป็นการปฏิบัติที่ไม่ดี
xuiqzy

12

วิธีเปลี่ยนการออกอากาศทั่วโลกเป็น LocalBroadcast

1) สร้างอินสแตนซ์

LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);

2) สำหรับการลงทะเบียน BroadcastReceiver

แทนที่

registerReceiver(new YourReceiver(),new IntentFilter("YourAction"));

กับ

localBroadcastManager.registerReceiver(new YourReceiver(),new IntentFilter("YourAction"));

3) สำหรับส่งข้อความออกอากาศ

แทนที่

sendBroadcast(intent);

กับ

localBroadcastManager.sendBroadcast(intent);

4) สำหรับการยกเลิกการลงทะเบียนข้อความออกอากาศ

แทนที่

unregisterReceiver(mybroadcast);

กับ

localBroadcastManager.unregisterReceiver(mybroadcast);

ฉันจะลงทะเบียน IntentFilter หลายตัวได้อย่างไร?
Parikshit Chalke

@ParikshitChalke: ลิงก์
XMAN

6

เมื่อคุณเล่นได้เพียงพอกับ LocalBroadcastReceiver ฉันจะแนะนำให้คุณลองใช้EventBus ของ Green Robot - คุณจะรู้ถึงความแตกต่างและประโยชน์ของมันเมื่อเทียบกับ LBR รหัสน้อยปรับแต่งเกี่ยวกับเธรดของผู้รับ (UI / Bg) ตรวจสอบความพร้อมของผู้รับเหตุการณ์เหนียวเหตุการณ์สามารถใช้เป็นข้อมูลการจัดส่ง ฯลฯ


2

ตัวอย่างของกิจกรรมและการดำเนินการบริการ LocalBroadcastManager สามารถพบได้ในนักพัฒนาเอกสาร โดยส่วนตัวแล้วฉันพบว่ามันมีประโยชน์มาก

แก้ไข: ลิงก์นั้นถูกลบออกจากเว็บไซต์แล้ว แต่มีข้อมูลต่อไปนี้: https://github.com/carrot-garden/android_maven-android-plugin-samples/blob/master/support4demos/src/com/ ตัวอย่าง / Android / supportv4 / เนื้อหา / LocalServiceBroadcaster.java


0
enter code here if (createSuccses){
                        val userDataChange=Intent(BRODCAST_USER_DATA_CHANGE)
                        LocalBroadcastManager.getInstance(this).sendBroadcast(
                            userDataChange
                        )
                        enableSpinner(false)
                        finish()

0

โดยการประกาศหนึ่งไฟล์ใน AndroidManifest.xml ด้วยแท็ก (หรือที่เรียกว่าสแตติก)

<receiver android:name=".YourBrodcastReceiverClass"  android:exported="true">
<intent-filter>
    <!-- The actions you wish to listen to, below is an example -->
    <action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>

คุณจะสังเกตเห็นว่าเครื่องรับสัญญาณออกอากาศที่ประกาศไว้ข้างต้นมีคุณสมบัติของ export =” true” แอ็ตทริบิวต์นี้บอกผู้รับว่าสามารถรับการถ่ายทอดจากนอกขอบเขตของแอปพลิเคชัน
2. หรือแบบไดนามิกโดยการลงทะเบียนอินสแตนซ์กับ registerReceiver (สิ่งที่เรียกว่าบริบทที่ลงทะเบียน)

public abstract Intent registerReceiver (BroadcastReceiver receiver, 
            IntentFilter filter);

public void onReceive(Context context, Intent intent) {
//Implement your logic here
}

มีสามวิธีในการส่งการออกอากาศ:
วิธี sendOrderedBroadcast ทำให้แน่ใจว่าการส่งการออกอากาศไปยังผู้รับเพียงคนเดียวในแต่ละครั้ง การออกอากาศแต่ละครั้งสามารถส่งผ่านข้อมูลไปยังรายการที่ติดตามหรือเพื่อหยุดการแพร่กระจายของการออกอากาศไปยังเครื่องรับที่ตามมา
sendBroadcast คล้ายกับวิธีการดังกล่าวข้างต้นมีความแตกต่างอย่างใดอย่างหนึ่ง เครื่องรับสัญญาณออกอากาศทั้งหมดได้รับข้อความและไม่ต้องพึ่งพาเครื่องอื่น
กระบวนการ LocalBroadcastManager.sendBroadcast ส่งการออกอากาศไปยังผู้รับที่กำหนดภายในแอปพลิเคชันของคุณเท่านั้นและไม่เกินขอบเขตของแอปพลิเคชันของคุณ


-4

เรายังสามารถใช้อินเตอร์เฟสเช่นเดียวกับ BroadcastManger ที่นี่ฉันกำลังแบ่งปันรหัส testd สำหรับ BroadcastManager แต่โดยการเชื่อมต่อ

สร้างอินเทอร์เฟซเช่น:

public interface MyInterface {
     void GetName(String name);
}

2- นี่คือชั้นแรกที่ต้องมีการใช้งาน

public class First implements MyInterface{

    MyInterface interfc;    
    public static void main(String[] args) {
      First f=new First();      
      Second s=new Second();
      f.initIterface(s);
      f.GetName("Paddy");
  }
  private void initIterface(MyInterface interfc){
    this.interfc=interfc;
  }
  public void GetName(String name) {
    System.out.println("first "+name);
    interfc.GetName(name);  
  }
}

3- นี่คือคลาสที่สองที่ใช้อินเทอร์เฟซเดียวกันซึ่งวิธีการเรียกโดยอัตโนมัติ

public class Second implements MyInterface{
   public void GetName(String name) {
     System.out.println("Second"+name);
   }
}

ดังนั้นโดยวิธีนี้เราสามารถใช้อินเตอร์เฟสที่ทำงานเหมือนกับ BroadcastManager

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