前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android开发笔记(四十二)Broadcast的生命周期

Android开发笔记(四十二)Broadcast的生命周期

作者头像
aqi00
发布2019-01-18 10:40:58
1.8K0
发布2019-01-18 10:40:58
举报
文章被收录于专栏:老欧说安卓

Broadcast是什么

广播的特性

广播(Broadcast)用于Android组件之间的灵活通信,它与Activity和Service的区别在于: 1、Activity和Service都只能一对一地通信,而Broadcast可以一对多,一人发送广播,多人接收处理; 2、对于发送者来说,广播不需要考虑接收者有没有在工作,接收者有在工作则接收广播,不在工作则丢弃广播; 3、对于接收者来说,会收到各式各样的广播,所以接收者首先要自行过滤符合条件的,然后才能进行解包处理; 4、通常情况下,Activity和Service都是在线程内部通信,而Broadcast既可用于线程内通信,也可用于线程间通信,还能用于进程间通信;

广播的用途

实际开发中,广播一般有以下用途: 1、适用于在不同代码文件中操纵对方页面控件的场景,比如说FragmentActivity与Fragment代码间通信,以及Activity与Adapter代码间通信; 2、适用于不同线程之间的通信,虽然线程间通信可使用Thread+Handler、AsyncTask等方式,但是广播的适应面显然更广,Android总线通信框架EventBus就是基于Broadcast来构建的; 3、适用于不同进程之间的通信,既可用于不同APP之间的通信,也可用于系统与APP之间的通信;

Broadcast的调用

广播的调用方法

sendBroadcast : 发送广播 registerReceiver : 注册接收器,一般在onStart或者onResume方法中注册 unregisterReceiver : 注销接收器,一般在onStop或者onPause方法中注销

进程内广播与进程间广播

如果广播是在应用之内使用,即不需要跨进程,可以考虑使用LocalBroadcastManager,因为这样更有效率(不需要跨进程通信),而且不用考虑广播开放造成的安全问题(如果其他应用也能收到广播的话)。 进程内广播,推荐使用LocalBroadcastManager类下的registerReceiver和unregisterReceiver方法,代码示例如下:

代码语言:javascript
复制
//注册接收器
LocalBroadcastManager.getInstance(this).registerReceiver(guestReceiver, filter);
//注销接收器
LocalBroadcastManager.getInstance(this).unregisterReceiver(guestReceiver);

进程间通讯,推荐使用Context类下的registerReceiver和unregisterReceiver方法,代码示例如下:

代码语言:javascript
复制
//注册接收器,如在activity使用,可去掉mContext,直接调用registerReceiver和unregisterReceiver
mContext.registerReceiver(guestReceiver, filter);
//注销接收器
mContext.unregisterReceiver(guestReceiver);

Broadcast的生命周期

发送广播

发送广播很简单,只管把请求发出去,不关心请求的处理结果,代码示例如下:

代码语言:javascript
复制
Intent intent = new Intent("com.example.exmbrdlife.fragment");
intent.putExtra("guest", "孙悟空");
//发送全局广播
//mContext.sendBroadcast(intent);
//发送本地广播
LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);

接收广播的方式

广播接收分动态注册、静态注册、嵌套注册三种方式。 动态注册,指的是在代码中调用方法registerReceiver和unregisterReceiver;它的生命周期开始于registerReceiver,结束于unregisterReceiver,通常伴随某个Activity的生命周期。 静态注册,指的是在AndroidManifest.xml中注册receiver接收器,receiver节点与activity和service节点是平级关系;它的生命周期开始于系统启动,结束于系统关机,在系统运行过程中,只要收到符合条件的广播,接收器便会启动工作。下面是在xml文件中静态注册的例子:

代码语言:javascript
复制
        <receiver android:name="com.app.mastersec.notify.BootReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />


                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </receiver>

嵌套注册,也要在AndroidManifest.xml中注册receiver接收器。它与静态注册的区别在于:静态注册的receiver代码是单独的java文件,而嵌套注册的receiver代码是嵌入在某个java类中,所以注册时要在receiver类名前加上“属主类名$”。另外,嵌套注册的receiver类在定义时也要加上static标记,这样才能正常访问。下面是在xml文件中嵌套注册的例子:

代码语言:javascript
复制
        <receiver android:name=".DownloadActivity$DownloadCompleteReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
            </intent-filter>
        </receiver>

接收APP广播(动态注册方式)

接收APP广播即可采用动态注册也可采用静态注册,下面代码以动态注册方式举例说明:

代码语言:javascript
复制
	@Override
	public void onStart() {
		super.onStart();
		guestReceiver = new GuestReceiver();
		IntentFilter filter = new IntentFilter("com.example.exmbrdlife.fragment");
		LocalBroadcastManager.getInstance(this).registerReceiver(guestReceiver, filter);
	}


	@Override
	public void onStop() {
		LocalBroadcastManager.getInstance(this).unregisterReceiver(guestReceiver);
		super.onStop();
	}


    private GuestReceiver guestReceiver;
    private class GuestReceiver extends BroadcastReceiver {


        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent != null) {
                String guest = intent.getStringExtra("guest");
                Toast.makeText(MainActivity.this, "您的客人是"+guest, Toast.LENGTH_LONG).show();
            }
        }
    }

注意上面在注册广播时使用了IntentFilter类来过滤,只有符合过滤条件的广播才会被接收处理。

接收系统广播(静态注册方式)

接收系统广播只能使用静态注册方式,下面代码以系统开机广播作为例子,xml修改部分在上面AndroidManifest.xml例子中给出了:

代码语言:javascript
复制
import com.app.mastersec.util.ServiceUtil;


import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import com.app.mastersec.util.LogUtil;


public class BootReceiver extends BroadcastReceiver {
	private static final String TAG = "BootReceiver";


	@Override
	public void onReceive(Context context, Intent intent) {
		if (intent != null) {
			if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
				//在系统开机后启动该APP的服务
				if (ServiceUtil.isWorked(context, ServiceUtil.notify_service) != true) {
					LogUtil.debug(TAG, "receive boot action, start service");
					Intent mIntent = new Intent(context, NotifyService.class);
					Bundle bundle = new Bundle();
					bundle.putInt("start_type", NotifySend.SYSTEM_BOOT);
					mIntent.putExtras(bundle);
					context.startService(mIntent);
				}
			}
		}
	}

}

系统广播列表

下面是几个常用的系统广播说明: Intent类 ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED"; //系统启动完毕,注意要想响应该广播的话,还需增加权限RECEIVE_BOOT_COMPLETED     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> ACTION_TIME_TICK = "android.intent.action.TIME_TICK"; //每分钟一次的广播 ACTION_TIMEZONE_CHANGED = "android.intent.action.TIMEZONE_CHANGED"; //时区设置改变 ACTION_DATE_CHANGED = "android.intent.action.DATE_CHANGED"; //日期设置改变 ACTION_TIME_CHANGED = "android.intent.action.TIME_SET"; //时间设置改变 ACTION_ALARM_CHANGED = "android.intent.action.ALARM_CHANGED"; //闹钟设置改变 ACTION_BATTERY_CHANGED = "android.intent.action.BATTERY_CHANGED"; //电池电量改变 ACTION_SCREEN_OFF = "android.intent.action.SCREEN_OFF"; //屏幕保护 ACTION_SCREEN_ON = "android.intent.action.SCREEN_ON"; //屏幕恢复 ConnectivityManager类 CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE"; //网络连接改变 WifiManager类 WIFI_STATE_CHANGED_ACTION = "android.net.wifi.WIFI_STATE_CHANGED"; //wifi状态改变

Broadcast的演示例子

为加深对广播用法的理解,下面给出一个ActionBar与ViewPager结合的例子,在Fragment中控制ActionBar的背景。正好博主也复习下ActionBar中标签页的使用,相关博文见《Android开发笔记(二十)顶部导航栏ActionBar》。 我们知道,把ActionBar的导航模式设置为ActionBar.NAVIGATION_MODE_TABS,即可在导航栏下方调用addTab方法添加具体标签页,通过点击标签页来切换ViewPager页面,从而实现完整的Tab页切换效果。Tab标签页的点击事件需要注册监听器TabListener,在onTabSelected方法中指定当前的ViewPager页面;同样ViewPager的翻页事件也需注册监听器OnPageChangeListener,在onPageSelected方法中指定当前的Tab标签。关键方法onTabSelected和onPageSelected的代码示例如下:

代码语言:javascript
复制
	@Override
	public void onTabSelected(Tab tab, FragmentTransaction ft) {
		mViewPager.setCurrentItem(tab.getPosition());
	}


	@Override
	public void onPageSelected(int arg0) {
		mActionBar.selectTab(mActionBar.getTabAt(arg0));
	}

上面可以看到,ViewPager通过setCurrentItem方法来设置当前页面,而Tab要稍复杂些,用到的有三个方法,分别是getPosition(获取当前Tab的位置)、getTabAt(获取指定位置的Tab)、selectTab(设置当前选中的Tab)。 限于篇幅,完整代码就不贴了,有需要的朋友可以在评论中留下邮箱,我看到后把实例工程给你发过去。下面是广播测试示例工程的效果图:

点击下载本文用到的Broadcast生命周期的工程代码 点此查看Android开发笔记的完整目录

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016年01月08日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Broadcast是什么
    • 广播的特性
      • 广播的用途
      • Broadcast的调用
        • 广播的调用方法
          • 进程内广播与进程间广播
          • Broadcast的生命周期
            • 发送广播
              • 接收广播的方式
                • 接收APP广播(动态注册方式)
                  • 接收系统广播(静态注册方式)
                    • 系统广播列表
                    • Broadcast的演示例子
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档