• Android 四大组件之BroadcastReceiver


    1.BroadcastReceiver简介:

      BroadcastReceiver 广播接收器,这个组件本质上就是一种全局监听器,用于监听全局广播(Broadcast)消息,因此它可以非常方便的实现系统不同组件之间的通信。

      BroadcastReceiver这个监听器与普通的onXxxListener监听器是不同的,onXxxListener是属于应用程序级别的监听器,当程序退出的时候那么这个监听器也就随之结束了。而BroadcastReceiver(配置文件中注册)属于系统级别的监听器,它拥有自己的进程,只要存在与之匹配的Broadcast以intent形式传递过来,那么BroadcastReceiver就会被激活。

      与Activity不同的是,当系统通过Intent启动指定的Activity组件时,如果系统没有找到目标Activity组件,这时就会发生程序异常中断,但系统通过Intent激活BroadcastReceiver时,即使没有找到目标BroadcastReceiver时,系统也不会有任何问题

    2.创建BroadcastReceiver

      2.1 首先需要继承BroadcastReceiver类,重写这个类里面的onReceive()方法,代码如下:

        

     1 package com.example.administrator.broadcastreceivertest;
     2 
     3 import android.content.BroadcastReceiver;
     4 import android.content.Context;
     5 import android.content.Intent;
     6 import android.util.Log;
     7 import android.widget.Toast;
     8 
     9 
    10 public class MyBroadcastReceiver extends BroadcastReceiver{
    11     public MyBroadcastReceiver() {
    12         Log.i("tag","创建构造器...");
    13     }
    14 
    15     @Override
    16     public void onReceive(Context context, Intent intent) {
    17         String msg = intent.getStringExtra("msg");
    18         Toast.makeText(context,msg,Toast.LENGTH_SHORT).show();
    19     }
    20 }

        当一个BroadcastReceiver被激活之后,系统会为之创建一个BroadcastReceiver实例,并自动触发它的onReceive()方法,onReceive()方法被执行完后,BroadcastReceiver实例就会被销毁。如果BroadcastReceiver的onReceive()方法不能在10s内执行完成,Android会认为该程序无响应,所以不要在onReceive()方法中执行耗时操作,否则会弹出ANR(Application No Response)对话框。

        如果在onReceive()方法中需要执行耗时操作,可以考虑使用Intent启动一个Service来完成操作,此时不应该考虑启动一个新的线程去处理耗时操作,因为BroadcastReceiver的生命周期很短,可能子线程还没有结束,BroadcastReceiver就已经退出了。而如果BroadcastReceiver所在的进程结束了,那么该线程就会标记为一个空线程。根据Android内存管理策略,在系统内存紧张时,会根据优先级首先结束优先级低的线程,而空线程优先级无疑是拥有最低的优先级,系统回收后,线程就无法完成相关操作了

      2.2 注册BroadcastReceiver

        注册BroadcastReceiver的两种方式:

          1>使用代码进行指定(动态注册),调用Context类提供的registerReceiver(BroadcastReceiver receiver,IntentFilter filter);代码如下

            

    1      MyBroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver();
    2         IntentFilter filter = new IntentFilter(SHOW_MESSAGE);
    3         registerReceiver(myBroadcastReceiver,filter);

          IntentFilter 是根据SHOW_MESSAGE用来匹配Broadcast的,SHOW_MESSAGE是一个自定义的静态字符串常量。

          要注意的是,BroadcastReceiver注册的地方,google 官方指出:

          Note:    If registering a receiver in your Activity.onResume() implementation, you should unregister it in Activity.onPause(). (You won't receive intents when paused, and this will cut down on unnecessary system overhead). Do not unregister in Activity.onSaveInstanceState(), because this won't be called if the user moves back in the history stack.

          意思大概是:如果你要在Activity类中的onResume()方法中注册一个receiver,你也应该在Activity类onPause()方法中取消注册。不要在onSaveInstanceState()方法中取消注册,因为如果用户退出当前Activity(从task中移除Activity)时,那么这个BroadcastReceiver也将不能被激活。

          特点:当应用程序关闭后,就不再监听。对于我们开发的App来说,越省电就会越受用户的欢迎,所以对于那些没有必要在应用程序退出后仍然进行监听的receiver,在代码中注册是一个不错的选择

          2>在AndroidManifest.xml中注册(静态注册),代码如下:

          

    1       <receiver android:name=".MyBroadcastReceiver">
    2             <intent-filter>
    3                 <action android:name="com.example.administrator.broadcastreceiver.SEND_MESSAGE"/>
    4             </intent-filter>
    5         </receiver>

           特点:不管应用程序是否处于活动状态,都会进行监听。比如某个应用程序监听内存使用情况,当在手机上安装好之后,不管其处于什么状态都会监听内存状态。

      2.3 生命周期

        BroadcastReceiver的生命周期很简单,如下图

        

    3.Broadcast介绍

      3.1Broadcast被分为两种:

        1>Normal Broadcast(普通广播):

          Normal Broadcast是完全异步的,可以在同一时刻,被所有接收者接收到(逻辑上),消息传递效率比较高。缺点是接收者不能将结果传给下一个接收者,并且无法阻止Broadcast Intent的传播

        2>Ordered Broadcast(有序广播):

          Ordered Broadcast的接收者将按照预先声明的优先级次序依次接收Broadcast。如果priority:A>B>C,那么Broadcast先传给A->B->C。

      3.2 发送广播的两种方式:

        1>sendBroadcast():发送Normal Broadcast

        2>sendOrderedBroadcast():发送Ordered Broadcast     

        对于Ordered Broadcast而言系统会根据接收者声明的优先级别按顺序依次执行接收者,优先收到Broadcast的接收者可以终止Broadcast(调用BroadcastReceiver的abortBroadcast()方法),那么后面的接收者将无法取到Broadcast.

        不仅如此,对于Ordered Broadcast而言,优先级别高的接收者,可以通过setResultExtras(Bundle bundle)将结果存到Broadcast中,下一个接收者可以通过Bundle bundle = getResultExtras(true)获取上一个数据

        TIP:系统接收短信,发出的Broadcast属于Ordered Broadcast.如果想拦截用户收到短信,可以设置优先级,让自定义的BroadcastReceiver先接收到短信,然后终止broadcast。

    4.下面是一个Ordered Broadcast广播例子,代码如下:

      MainActivity类:

     1 package com.example.administrator.broadcastreceivertest;
     2 
     3 import android.app.Activity;
     4 import android.content.Intent;
     5 import android.os.Bundle;
     6 import android.view.View;
     7 
     8 
     9 public class MainActivity extends Activity {
    10 
    11     private static final String SHOW_MESSAGE = "com.example.administrator.broadcastreceiver.SEND_MESSAGE";
    12     @Override
    13     protected void onCreate(Bundle savedInstanceState) {
    14         super.onCreate(savedInstanceState);
    15         setContentView(R.layout.activity_main);
    16     }
    17 
    18     public void sendOrderedBroadcast(View view){
    19         Intent intent = new Intent(SHOW_MESSAGE);
    20         intent.putExtra("msg","Ordered Broadcast");
    21         sendOrderedBroadcast(intent,null);
    22     }
    23 
    24 }

      MyBroadcastReceiver类

      

     1 package com.example.administrator.broadcastreceivertest;
     2 
     3 import android.content.BroadcastReceiver;
     4 import android.content.Context;
     5 import android.content.Intent;
     6 import android.util.Log;
     7 import android.widget.Toast;
     8 
     9 
    10 public class MyBroadcastReceiver extends BroadcastReceiver{
    11 
    12     @Override
    13     public void onReceive(Context context, Intent intent) {
    14         String msg = intent.getStringExtra("msg");
    15         Log.i("tag","MyBroadcastReceiver:"+msg);
    16         Toast.makeText(context,"MyBroadcastReceiver:"+msg,Toast.LENGTH_SHORT).show();
    17     }
    18 }

      MyBroadcastReceiver2类

      

     1 package com.example.administrator.broadcastreceivertest;
     2 
     3 import android.content.BroadcastReceiver;
     4 import android.content.Context;
     5 import android.content.Intent;
     6 import android.util.Log;
     7 import android.widget.Toast;
     8 
     9 
    10 public class MyBroadcastReceiver2 extends BroadcastReceiver{
    11 
    12     @Override
    13     public void onReceive(Context context, Intent intent) {
    14         String msg = intent.getStringExtra("msg");
    15         Log.i("tag","MyBroadcastReceiver2:"+msg);
    16         Toast.makeText(context,"MyBroadcastReceiver2:"+msg,Toast.LENGTH_LONG).show();
    17     }
    18 }

      activity_main.xml

     1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     2     xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
     3     android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
     4     android:paddingRight="@dimen/activity_horizontal_margin"
     5     android:paddingTop="@dimen/activity_vertical_margin"
     6     android:orientation="vertical"
     7     android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
     8 
     9 
    10     <Button
    11         android:layout_width="wrap_content"
    12         android:layout_height="wrap_content"
    13         android:text="发送 Ordered Broadcast "
    14         android:onClick="sendOrderedBroadcast"/>
    15 </LinearLayout>

      AndroidManifest.xml

      

     1 <?xml version="1.0" encoding="utf-8"?>
     2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     3     package="com.example.administrator.broadcastreceivertest" >
     4 
     5     <application
     6         android:allowBackup="true"
     7         android:icon="@drawable/ic_launcher"
     8         android:label="@string/app_name"
     9         android:theme="@style/AppTheme" >
    10         <activity
    11             android:name=".MainActivity"
    12             android:label="@string/app_name" >
    13             <intent-filter>
    14                 <action android:name="android.intent.action.MAIN" />
    15 
    16                 <category android:name="android.intent.category.LAUNCHER" />
    17             </intent-filter>
    18         </activity>
    19 
    20 
    21         <receiver android:name=".MyBroadcastReceiver">
    22             <intent-filter  android:priority="1">
    23                 <action android:name="com.example.administrator.broadcastreceiver.SEND_MESSAGE"/>
    24             </intent-filter>
    25         </receiver>
    26 
    27         <receiver android:name=".MyBroadcastReceiver2">
    28             <intent-filter android:priority="2">
    29                 <action android:name="com.example.administrator.broadcastreceiver.SEND_MESSAGE"/>
    30             </intent-filter>
    31         </receiver>
    32     </application>
    33 
    34 </manifest>

    运行结果:

    控制台输出结果:

    从运行结果可以看出先是MyBroadcastReceiver2先接收到Broadcast,接着才是MyBroadcastReceiver,因为我在注册时将MyBroadcastReceiver2的优先级设置为2,MyBroadcastReceiver优先级为1。

  • 相关阅读:
    Mac下PyCharm快捷键大全
    SQL语句优化
    There was a problem confirming the ssl certificate: [SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol version (_ssl.c:661)
    Hadoop Trash回收站使用指南
    HDFS 中向 DataNode 写入数据失败了怎么办
    mapreduce 实现写出orc文件
    mapreduce读取压缩文件
    hive开窗函数over(partition by ......)用法
    Mac 安装 home Brew以及 XCTool的过程记录
    iOS开发中使用CocoaPods来管理第三方的依赖程序
  • 原文地址:https://www.cnblogs.com/xsyulinzi/p/4307411.html
Copyright © 2020-2023  润新知