Android复习(Android基础-四大组件)——Broadcast

1. 广播分类

  1. 广播的发送方式:标准广播、有序广播、粘性广播
  2. 广播的类型:系统广播、本地广播

1.1 标准广播

  • 完全异步,无序的广播
  • 发出后,所有的广播接收器几乎都会在同一时间收到消息。(异步)
  • 但是消息无法截断。(无序)
  • 消息可以通过sendBroadcast()方法发送
    在这里插入图片描述

1.2 有序广播

  • 同步的广播
  • 在广播发送出去之后,同一时刻只能有一个广播接收器收到消息,当这个广播接收器处理完毕后,其他广播接收器才能收到消息。
  • 过程
    1. 通过sendOrderedBroadcast(intent)发送,发送出去的同步的广播被Receiver按照优先级先后顺序接收,相同优先级的动态注册的广播优先。
    2. 每次只能有一个接收者收到,接收者收到后,可以通过setResultData来传递数据给下一个接收者,也可以通过abortBroadcast()来终止广播继续向下传递。
  • 设置优先级的方式(AndroidManifest.xml)
<receiverandroid:name=".MyReceiver"android:enabled="true"android:exported="true"><intent-filterandroid:priority="100"></intent-filter>
</receiver>

在这里插入图片描述

1.3 粘性广播

  • 类似于粘性事件
  • 粘性广播发送后就会一直存在系统的消息容器里面,等待对应的处理器去处理。
  • 如果暂时没有处理器处理这个消息,则一直在消息容器里面处于等待状态,粘性广播的Receiver如果被销毁,那么下次重建时会自动接收到消息数据。

1.4 系统广播

  • 系统会在发生各种系统事件时自动发送广播。
    • 例如当系统进入和退出飞行模式时,系统广播就会发送给所有同意接收相关事件的应用。
    • 系统内置的广播,比如开启、锁屏、时间等等(一般都是有序广播)
      在这里插入图片描述

1.5 本地广播

  • 广播理论上是所有注册这个广播接收器的人都能收到,那么会存在恶意注册我们对应的广播接收器,来接收到我们的广播。可能造成隐私泄露。

  • 所以我们让广播只能在本应用内传播,外部无法接收。只在当前程序内生效的广播

  • 在Manifest.xml中将Receiver的exported属性改为false,即可以让该广播接收器只接收本地广播。

2. 广播接收器的注册

  • 创建一个类,继承BroadcastReceiver类,并重写onReceive方法。这样当有广播来时,onReceive就会收到消息被调用。
    在这里插入图片描述

2.1 静态注册(Manifest)

  • 在AndroidManifest文件中声明一下这个广播,并在<receiver>字段里面的<intent-filter>添加需要接收的广播action即可。

  • 从Android8.0开始,隐式广播就不允许通过系统注册(静态注册)的方式来接收了,这样是为了防止APP通过此方法唤醒、保活、导致大量APP处于活跃状态,进而系统卡顿。

  1. 隐式广播:隐式广播就是没有指明接收程序的广播
  2. 广播为什么能唤醒:系统软件包管理器会在应用安装时注册receiver。然后接收器会成为应用的一个独立入口,这意味着如果应用当前未运行,系统可以启动应用并发送广播。只要注册上下文有效,上下文注册的接受者就会接收广播。
  3. 系统广播:大多数系统广播都是隐式广播,不过少数的系统广播不是,所以可以监听。(开机启动,下面的案例)
  4. 解决方法
    1. 尽量使用动态注册代替静态注册
    2. 如果必须要使用静态注册的话,那么就得在创建Intent后调用setComponent设置Component(启动指定Receiver接收),然后其他注册广播的步骤和原来在Android6.0系统一下注册的方法一样。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"package="com.example.broadcasttest"><!--监听系统开机广播也需要声明权限,可以看到,我们使用<user-permission>标签里又加入了一条android.permission.RECEIVE_BOOT_COMPLETED权限。--><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Theme.Broadcasttest">...<receiverandroid:name=".MainActivty$BootCompleteReceiver"android:enabled="true"android:exported="true"tools:ignore="Instantiatable"><!--由于Android系统启动完成后会发出一条值为android.intent.action.BOOT_COMPLETED的广播,因此我们在<intent-filter>标签里添加了相应的action。--><intent-filter><action android:name="android.intent.action.BOOT_COMPLETED"/></intent-filter></receiver></application>
</manifest>

2.2 动态注册

  1. 首先创建一个IntentFilter实例,使用addAction方法添加对应的action
  2. 创建自定义的广播接收器对象Receiver。
  3. 通过registerReceiver(receiver , intentFilter)传入 接收器对象 和 intentFilter对象实现注册。
  • 动态注册中,广播一定要在onDestroy方法中调用unregisterReceiver方法取消注册,否则会发生内存泄露。
  • onReceive方法中不能执行耗时操作,因为广播接收器中不允许开启线程
    在这里插入图片描述
IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
BroadcastReceiver br = new MyBroadcastReceiver();
this.registerReceiver(br, filter);//非静态内部类——接收器
public class MyBroadcastReceiver extends BroadcastReceiver {private static final String TAG = "MyBroadcastReceiver";@Overridepublic void onReceive(Context context, Intent intent) {StringBuilder sb = new StringBuilder();sb.append("Action: " + intent.getAction() + "\n");sb.append("URI: " + intent.toUri(Intent.URI_INTENT_SCHEME).toString() + "\n");String log = sb.toString();Log.d(TAG, log);Toast.makeText(context, log, Toast.LENGTH_LONG).show();}}
  • 只要注册上下文有效,上下文注册的BroadcastReceiver就会接收广播
  • 如果您在 Activity 上下文中注册,只要 Activity 没有被销毁,您就会收到广播。如果您在Application上下文中注册,只要Application在运行,您就会收到广播。

3. 发送广播

3.1 发送标准广播

  1. 创建一个Intent对象,构造方法中传入需要的action
  2. 调用setPackage指明发送给的应用
  3. 通过sendBroadcast发送这个Intent
<receiverandroid:name=".MyReceiver"android:enabled="true"android:exported="true"><intent-filter><action android:name="com.example.allbroadcasttest.MY_BROADCAST"/></intent-filter>
</receiver>    
  • 为什么现在一定要设置发送的包名?
  • 自定义广播默认是隐式广播(不能在静态注册下发送)
  • 所以指定这条广播发给哪个程序,变成显示广播。
@Override
public void onClick(View v){Intent intent = new Intent("com.example.allbroadcasttest.MY_BROADCAST");intent.setComponent(new ComponentName(getPackageName() , "com.example.allbroadcasttest.MY_BROADCAST"));sendBroadcast(intent);
}    

在这里插入图片描述

3.2 发送有序广播

  • 也是构造一个对象,区别在于发送广播的方式变成了sendOrderBroadcast方法。
  1. 需要两个参数,一个是Intent,另一个是与权限相关的,一般是null。
  2. 然后需要在receiver的AndroidManifest文件中receiver字段下面给广播设置个优先级。
  3. 如果有Receiver要截断广播,就调用abortBoardcast()。

3.3 发送本地广播(已被弃用)

  • 跟动态注册广播接收器一样,只不过在onCreate中创建LocalBroadcastReceiver对象。
  • 然后注册和发送都是调用LocalBroadcastManager的registerReceiver和sendBroadcast。

4. 相关问题

4.1 不取消注册广播会导致内存泄露吗?

在这里插入图片描述

4.2 广播中能执行耗时操作吗?

在这里插入图片描述

4.3 本地广播为什么被废弃了?

在这里插入图片描述

4.4 到底什么是广播?

在这里插入图片描述

4.5 短信用的是什么广播?

  • 系统广播
  • 会发出一套android.provider.Telephony.SMS_RECEIVED的action

4.6 显示和隐式广播的补充?

  • 所以不要用静态注册最好
  • 用了必须加 intent.setComponent(new ComponentName(getPackageName() ,"com.example.allbroadcasttest.MY_BROADCAST"));
  • 指定包名和类名
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/90872.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

获取部门完整路径数据

1: 获取部门数据 (基础) SELECT id, CONCAT(pid_path,id) as pid_path2,pid_path,title FROM web_department;2: 获取部门数据 (进阶, 但是是,分隔) SELECT t1.id, t1.title, CONCAT(t1.pid_path, ,, t1.id) AS pid_path,(SELECT GROUP_CONCAT(t2.title ORDER BY FIND_IN_SET…

Nginx环境搭建以及Docker环境部署

目录 Nginx环境搭建 1.首先创建Nginx的目录并进入 2.下载Nginx的安装包 可以通过FTP工具上传离线环境包&#xff0c;也可通过wget命令在线获取安装包 没有wget命令的可通过yum命令安装 3.解压Nginx的压缩包 4.下载并安装Nginx所需的依赖库和包 安装方式一 安装方式二 --- 也…

NLP文本匹配任务Text Matching [无监督训练]:SimCSE、ESimCSE、DiffCSE 项目实践

NLP文本匹配任务Text Matching [无监督训练]&#xff1a;SimCSE、ESimCSE、DiffCSE 项目实践 文本匹配多用于计算两个文本之间的相似度&#xff0c;该示例会基于 ESimCSE 实现一个无监督的文本匹配模型的训练流程。文本匹配多用于计算两段「自然文本」之间的「相似度」。 例如…

TypeScript 关于对【泛型】的定义使用解读

目录 概念导读泛型函数多个泛型参数泛型约束泛型别名泛型接口泛型类总结&#xff1a; 概念导读 泛型&#xff08;Generics&#xff09;是指在定义函数、接口或类的时候&#xff0c;不预先指定具体的类型&#xff0c;而在使用的时候再指定类型的一种特性。使用泛型 可以复用类型…

C++入门

目录 一&#xff1a;关键字 二&#xff1a;命名空间 1.引入 2.命名空间的定义 <1>:命名空间中定义变量/函数/类型 <2>:命名空间可以嵌套 <3>:同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中 3.命名空…

【设计模式】建造者模式

建造者模式&#xff08;Builder Pattern&#xff09;使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式。 一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。 介绍 …

idea入门与maven配置的一些介绍

idea入门与maven配置的一些介绍 1.确保Java和Maven已安装2.创建一个新的Maven项目3.导航到要创建项目的目录配置Maven4.配置项目的pom.xml文件5.配置其他Tomcat和设置jdk6.构建和运行项目 关于idea入门基础配置 步骤1&#xff1a;安装IntelliJ IDEA 首先&#xff0c;从IntelliJ…

【Vue-Router】命名视图

命名视图 同时 (同级) 展示多个视图&#xff0c;而不是嵌套展示&#xff0c;例如创建一个布局&#xff0c;有 sidebar (侧导航) 和 main (主内容) 两个视图&#xff0c;这个时候命名视图就派上用场了。 可以在界面中拥有多个单独命名的视图&#xff0c;而不是只有一个单独的出…

JVM内存区域划分

JVM把虚拟机的内存区域划分为方法区&#xff08;Method Area&#xff09;、堆&#xff08;Heap&#xff09;、栈&#xff08;Java Stack&#xff09;、本地方法栈&#xff08;Native Method Stack&#xff09;、和一个PC寄存器&#xff08;程序计数器&#xff0c;Progam Counti…

msvcp140.dll如何重新安装?快速安装msvcp140.dll的方法分享

msvcp140.dll是Windows操作系统的一个动态链接库文件&#xff0c;它是Microsoft Visual C Redistributable的一部分。这个文件在运行某些应用程序时非常重要。然而&#xff0c;在某些情况下&#xff0c;msvcp140.dll文件可能会损坏或遗失&#xff0c;导致应用程序无法正常运行。…

神经网络基础-神经网络补充概念-03-逻辑回归损失函数

概念 逻辑回归使用的损失函数通常是"对数损失"&#xff08;也称为"交叉熵损失"&#xff09;或"逻辑损失"。这些损失函数在训练过程中用于衡量模型预测与实际标签之间的差异&#xff0c;从而帮助模型逐步调整权重参数&#xff0c;以更好地拟合数…

堆的实现以及应用

&#x1f493;博主个人主页:不是笨小孩&#x1f440; ⏩专栏分类:数据结构与算法&#x1f440; 刷题专栏&#x1f440; C语言&#x1f440; &#x1f69a;代码仓库:笨小孩的代码库&#x1f440; ⏩社区&#xff1a;不是笨小孩&#x1f440; &#x1f339;欢迎大家三连关注&…

Unity zSpace 开发

文章目录 1.下载 zSpace 开发环境1.1 zCore Unity Package1.2 zView Unity Package 2. 导入工程3. 发布设置4.功能实现4.1 用触控笔来实现对模型的拖拽&#xff1a; 5. 后续更新 1.下载 zSpace 开发环境 官网地址 1.1 zCore Unity Package zSpace 开发核心必须 1.2 zView …

K8S系列三:单服务部署

写在前面 本文是K8S系列第三篇&#xff0c;主要面向对K8S新手同学&#xff0c;阅读本文需要读者对K8S的基本概念&#xff0c;比如Pod、Deployment、Service、Namespace等基础概念有所了解。尚且不熟悉的同学推荐先阅读本系列的第一篇文章《K8S系列一&#xff1a;概念入门》[1]…

图解 Paxos 算法

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱写博客的嗯哼&#xff0c;爱好Java的小菜鸟 &#x1f525;如果感觉博主的文章还不错的话&#xff0c;请&#x1f44d;三连支持&#x1f44d;一下博主哦 &#x1f4dd;个人博客&#xff1a;敬请期待 &#x1f4d5;系列…

ROS学习笔记(二)---使用 VScode 开发 ROS 的Python程序(简例)

一、任务介绍 本篇作为ROS学习的第二篇&#xff0c;是关于如何在Ubuntu18.04中使用VSCode编写一个Python程序&#xff0c;输出“Hello&#xff01;”的内容介绍。 首先我们来了解下ROS的文件系统&#xff0c;ROS文件系统级指的是在硬盘上ROS源代码的组织形式&#xff0c;其结构…

东方晶源亮相第十一届半导体设备年会,共话发展“芯”机遇

8月11日&#xff0c;以“协力同芯抢机遇&#xff0c;集成创新造设备”为主题的第十一届&#xff08;2023年&#xff09;中国电子专用设备工业协会半导体设备年会暨产业链合作论坛&#xff08;CSEAC&#xff09;在无锡太湖国际博览中心圆满闭幕。为期3天的CSEAC&#xff0c;通过…

安装Linux操作系统CentOS 6详细图文步骤

为满足业务对Linux操作系统部署的要求&#xff0c;本文档主要提供CentOS 6操作系统的最小化安装和基本配置, 安装本系统建议最少1GB内存和2GB磁盘空间。 1、 使用光盘或者挂载ISO镜像&#xff0c;在出现如下图形界面时选择【Install or upgrade an existing system】并按Ent…

Redis 缓存过期及删除

一、Redis缓存过期策略 物理内存达到上限后&#xff0c;像磁盘空间申请虚拟内存(硬盘与内存的swap),甚至崩溃。 内存与硬盘交换 (swap) 虚拟内存&#xff0c;频繁I0 性能急剧下降&#xff0c;会造成redis内存急剧下降&#xff1b; 一般设置物理内存的3/4&#xff0c;在redis…

【C/C++】STL queue 非线程安全接口,危险!

STL 中的 queue 是非线程安全的&#xff0c;一个组合操作&#xff1a;front(); pop() 先读取队首元素然后删除队首元素&#xff0c;若是有多个线程执行这个组合操作的话&#xff0c;可能会发生执行序列交替执行&#xff0c;导致一些意想不到的行为。因此需要重新设计线程安全的…