Android面经_111道安卓基础问题(四大组件BroadCast、内容提供者篇)

news2024/9/20 1:30:48

该文章涉及的内容主要是:BroadCast内容提供者

Android基础问题——四大组件之BroadCast、ContentProvider 内容提供者

  • 1、BroadCast
    • 1.1、Android的广播分类
    • 1.2、Android的广播注册方式
    • 1.3、广播作用域
  • 2、内容提供者`Content provider`
    • 2.1、什么是内容提供者?
    • 2.2、ContentProvider 是如何实现数据共享的?
    • 2.3、说说 ContentProvider、ContentResolver、ContentObserver 之间的关系?
    • 2.4、ContentProvider的权限管理
    • 2.5、为什么要使用通过ContentResolver类从而与ContentProvider类进行交互,而不直接访问ContentProvider类?
    • 2.6、ContentResolver和binder差异


1、BroadCast

1.1、Android的广播分类

广播在执行方式的角度上,可以分类为:

  • 标准广播-Normal broadcast
  • 有序广播-Ordered broadcast

标准广播一种完全异步执行的广播,所有的广播接收器都可以同时接收到这条广播,彼此没有先后之分,所有的接收者都是同等对待。

注意:标准广播无法被截断,例如:若A、B、C三人同时买彩票就是标准广播,彩票中心发出的中奖号码,A、B、C同时收到消息,无法阻止对方去拦截消息。

有序广播:按照顺序执行的广播方式,同一个时刻只有一个广播接收器能够接收到广播,并且优先级高的广播接收器最先接受到广播,除此之外,接收到广播的接收器还可以截断正在传递的广播,后续的广播接收器就无法收到这条广播了


1.2、Android的广播注册方式

广播在注册方式上可以分为:

  • 动态注册
  • 静态注册

动态注册:指的是在程序代码中进行广播注册的过程。如下展示了基于动态注册方式的广播代码结构。

@Override
protected void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);
	intentFilter = new IntentFilter();
	intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
	networkChangeReceiver = new NetworkChangeReceiver();
	registerReceiver(networkChangeReceiver, intentFilter);
}

@Override
protected void onDestroy() {
	super.onDestroy();
	unregisterReceiver(networkChangeReceiver);
}

class NetworkChangeReceiver extends BroadcastReceiver {
	@Override
	public void onReceiver(Context context, Intent intent) {
		ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo networkInfo = connectivityManager.getActivityNetworkInfo();
		if (networkInfo != null && networkInfo.isAvailable()) {
			Toast.makeText(context, "network is available...", Toast.LENGTH_SHORT);
		} else {
			Toast.makeText(context, "network is unavailable...", Toast.LENGTH_SHORT);
		}
	}
}
  • 首先,使用IntentFilter()设置自身期望捕获到的广播信号,这个信号要和发出的广播信号相同才会有响应。
  • 其次,内部类NetworkChangeReceiver()继承自BroadcastReceiver,需要监听广播信号的,都必须要继承该类,并且实现其中的onReceive方法。
  • 紧接着,registerReceiverNetworkChangeReceiver的对象和IntentFilter的对象进行注册,方便接收传来的广播信号。
  • 最后,unregisterReceiver取消了注册,任何注册了广播信号的对象都必须要实现取消注册的功能。

上面的代码实现在onCreate方法中,因此app需要打开才可以接收广播。

静态注册:指的是在AndroidManifest.XML中注册广播接收的过程,如下所示:
在这里插入图片描述

  • 外层大框:利用<receiver>标签,表明这是一个广播的接收器,在AS中,可以通过新建一个Broadcast Receiver来自动完成该部分的编写。
  • 里层小框“:同样使用了intent-filteraction,表明自身设置的广播信号,在使用权限时,务必记得声明自己需要的权限,否则程序会崩溃

1.3、广播作用域

主要分为如下:

  • 全局广播:指的是可以被其他任何应用程序都能接收到的广播,比如说Android系统发出的电量不足的广播,所有应用程序都能收到。
  • 本地广播:指的是只能在应用程序内部传递的广播信号,并且广播接收器也只能接收来自本程序发出的广播。

全局广播的代码实现

//定义一个继承BroadcastReceiver的MyReceiver类,实现onReceive方法
//onReceive方法会在匹配成功后调用,这里让它简单的显示一下即可
public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO: This method is called when the BroadcastReceiver is receiving
        // an Intent broadcast.
        Toast.makeText(context, "响应了自身设置的广播", Toast.LENGTH_SHORT).show();
    }
}

//这个是在AndroidManifest文件中,设置一个自定义的广播"com.example.globalbroadcast.MY_TEST"
//当接收到这条广播时,就会进行匹配,如果匹配成功,就会调用上面的onReceive方法
<receiver
      android:name=".MyReceiver"
      android:enabled="true"
      android:exported="true">
        <intent-filter>
          <action android:name="com.example.globalbroadcastdemo.MY_TEST"/>
        </intent-filter>
</receiver>


//这个是在MainActivity中实现的,设置了一个Button,当做广播信号的发送方。
//广播也仍然是使用intent来发送的,当按下Button,就会通过intent发送一条广播
//注意,这里用到了sendBroadcast()方法,这将发出一个全局广播,所有广播接收器都能收到这条广播
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button = findViewById(R.id.testMyBroadcast);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent("com.example.globalbroadcastdemo.MY_TEST");
                sendBroadcast(intent);
            }
        });
    }
}

由于全局广播存在一定的安全问题,因此Android提供了一种仅在App内部传递的广播机制:本地广播
本地广播实现和全局广播类似,但是本地广播需要调用LocalBroadcastManager来进行管理,细节存在不同:

// 本地广播的实现,调用了LocalBroadcastManager
// 本地广播仅在本应用程序内传播,外部其他的应用程序接收不到该广播发出的信号
public class MainActivity extends AppCompatActivity {
    /**
     * intentFilter 意图过滤器,设置自身需要监听的广播信号
     */
    private IntentFilter intentFilter;
    /**
     * localBroadcastManager 本地广播管理
     */
    private LocalBroadcastManager localBroadcastManager;
    /**
     * localReceiver 本地广播接收器
     */
    private LocalReceiver localReceiver;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 获取一个本地广播管理的对象
        localBroadcastManager = LocalBroadcastManager.getInstance(this);
        // 本地广播的发送者
        Button button = findViewById(R.id.testMyBroadcast);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent("com.example.globalbroadcastdemo.MY_LOCAL");
                localBroadcastManager.sendBroadcast(intent);
            }
        });
        // 设置自身需要监听的广播信号
        intentFilter = new IntentFilter();
        intentFilter.addAction("com.example.globalbroadcastdemo.MY_LOCAL");
        // 注册本地广播监听器
        localReceiver = new LocalReceiver();
        localBroadcastManager.registerReceiver(localReceiver, intentFilter);
    }

    //LocalReceiver 内部类,实现了onReceive方法
    class LocalReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {
            Toast.makeText(context, "收到了本地发出的广播", Toast.LENGTH_SHORT).show();
        }
    }
}

2、内容提供者Content provider

首先给出下图综视:
在这里插入图片描述

2.1、什么是内容提供者?

ContentProvider是Android的四大组件之一。ContentProvider 用来在不同的app之间实现数据共享,并且提供统一的接口。

ContentProvider是类似数据库中表的方式将数据暴露,也就是说ContentProvider就像一个数据库,外界获取其数据,类似于数据库的增删改查,只不过是采用URI来表示外界需要访问的“数据库”。

ContentProvider定义了一个对外开放的接口,从而可以让其他app使用我们自己应用中的文件、数据库内存储的信息。


2.2、ContentProvider 是如何实现数据共享的?

在Android中如果想将自己应用的数据,一般都是数据库中的数据,提供给第三发的应用,那么我们只能通过ContentProvider 来实现。

ContentProvider 是app之间共享数据的接口,使用的时候需要先定义一个类继承ContentProvider ,然后覆写query、insert、update、delete等方法,因为其四大组件之一因此必须在AndroidManifest 文件中进行注册,把自己的数据通过url的形式共享出去。

第三方可以通过ContentResolver 来访问该Provider。

URI介绍
每一个ContentResolver 都拥有一个公共的URI,只可以通过这个访问该URI来获得数据。

Android所提供的ContentResolver 都存放在android.provider包中,分为A、B、C、D4个部分:

  • A:标准前缀,用来说明一个ContentResolver 控制这些数据,无法改变。
  • B:URI的标识,用于唯一标识这个ContentResolver ,外部调用者可以根据这个标识来找到它,它定义了哪一个ContentResolver 提供的这些数据,对于第三方的App,为了保证URI的唯一性,它必须是一个完整的、小写的类名,这个标识在元素的authorities属性中说明:一般是定义该ContentProvider 的包,类的名称。
  • C:路径–path,通俗的讲就是你要操作的数据库中表的名字,或者你也可以自己定义,记得在使用的时候保持一致就行了,content://com.bing.provider.myprovider/tablename
  • D:如果URI中包含表示需要获取的记录的ID;则就返回该id对应的数据,如果没有ID,就表示返回全部;content://com.bing.provider.myprovider/tablename/# #表示数据id

2.3、说说 ContentProvider、ContentResolver、ContentObserver 之间的关系?

首先给出如下图:
在这里插入图片描述

1、ContentProvider:在Android中作用就是对外共享数据,就是说可以通过ContentProvider把app中的数据共享给其他的app访问,其他应用可以进行增删改查操作;

若采用文件操作模式对外共享数据,数据的访问方式会因为数据存储的方式而不同,从而无法统一数据访问的接口,例如:采用xml文件对外共享数 据,需要进行xml解析才能读取数据;采用sharedpreferences共享数据,需要使用sharedpreferences API读取数据。使用ContentProvider对外共享数据的好处是统一了数据的访问方式。

归纳如下:

  • 一个app实现ContentProvider来提供内容给别的应用来操作,通过ContentProvider来操作别的app数据,当然在自己的app中也可以。
  • 负责管理结构化数据的访问。
  • 封装数据并且提供一套定义数据安全的机制。
  • 不同进程之间数据访问的接口。
  • 为数据跨进程访问提供了一套安全的访问机制,对数据组织和安全访问提供了可靠的保证。

2、ContentResolver:内容解析者,可以以不同的URI操作不同的ContentProvider中的数据,外部进程可以通过ContentResolverContentProvider进行交互。

  • 内容解析者,用于获取内容提供者提供的数据
  • ContentResolver.notifyChange(uri)发出消息

3、ContentObserver:观察ContentObserver中的数据变化,并将变化通知给外界。

  • 内容监听器,可以监听数据的改变状态。
  • 目的是观察(捕捉)特定Uri引起的数据库的变化,继而做一些相应的处理,它类似于数据库技术中的触发器(Trigger),当ContentObserver所观察的Uri发生变化时,便会触发它。触发器分为表触发器、行触发器,相应地ContentObsever也分为表ContentObserver、行ContentObserver,当然这是与它所监听的Uri MIME Type有关的
  • ContentResolver.registerContentObserver()方法来监听消息。

2.4、ContentProvider的权限管理

对于ContentProvider暴露出来的数据,应该是存储自己引用内存中的数据,对于一些存储在外部存储器上的数据,并不能限制访问权限,使用ContentProvider就没有意义了,对于ContentProvider而言,有很多权限控制,可以在AndroidManifest文件中对节点属性进行配置,一般有如下设置:

  • android:grantUriPermssions:临时许可标志
  • android:permission:Provider读写权限
  • android:readPermission:Provider的读权限
  • android:writePermission:Provider的写权限
  • android:enabled:标记允许系统启动Provider
  • android:exported:标记允许其他应用程序使用这个Provider
  • android:multiProcess:标记允许系统启动Provider相同的进程中调用客户端

2.5、为什么要使用通过ContentResolver类从而与ContentProvider类进行交互,而不直接访问ContentProvider类?

一般来说,一款应用要使用多个ContentProvider,若需要了解每个ContentProvider的不同实现从而再完成数据交互,操作成本高 & 难度大,所以再ContentProvider类上加多了一个 ContentResolver类对所有的ContentProvider进行统一管理。

 // 外部进程向 ContentProvider 中添加数据
 public Uri insert(Uri uri, ContentValues values)

// 外部进程 删除 ContentProvider 中的数据
public int delete(Uri uri, String selection, String[] selectionArgs)

// 外部进程更新 ContentProvider 中的数据
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs)

// 外部应用 获取 ContentProvider 中的数据
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)

2.6、ContentResolver和binder差异

如下图所示:
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Google Protobuf 实践使用开发

Android 敏捷开发助手 Lottie动画 轻松使用PNG、JPG等普通图片高保真转SVG图Android 完美的蒙层方案Android MMKV框架引入使用强大无匹的自定义下拉列表Google Protobuf 实践使用开发 Protobuf 实践使用前言Protobuf基本介绍Protobuf 使用配置protobuf 基本语法1. 基本使用2. …

JavaWeb-Ajax

JavaWeb-Ajax 3&#xff0c;Ajax 3.1 概述 AJAX (Asynchronous JavaScript And XML)&#xff1a;异步的 JavaScript 和 XML。 我们先来说概念中的 JavaScript 和 XML&#xff0c;JavaScript 表明该技术和前端相关&#xff1b;XML 是指以此进行数据交换。 3.1.1 作用 AJAX…

用Python绘制傅里叶级数和泰勒级数逼近已知函数的动态过程

文章目录Taylor级数Fourier级数本文代码&#xff1a; Fourier级数和Taylor级数对原函数的逼近动画Taylor级数 级数是对已知函数的一种逼近&#xff0c;比较容易理解的是Taylor级数&#xff0c;通过多项式来逼近有限区间内的函数&#xff0c;其一般形式为 f(x)∑n0Nanxnf(x)\su…

Lua 运算符 - 较为特殊部分

Lua 运算符 - 较为特殊部分 参考至菜鸟教程。 算术运算符 操作符描述实例^乘幂A^2 输出结果 100-负号-A 输出结果 -10//整除运算符(>lua5.3)5//2 输出结果 2在 lua 中&#xff0c;/ 用作除法运算&#xff0c;计算结果包含小数部分&#xff0c;// 用作整除运算&#xff0c;计…

Shiro学习文档

Shiro Java安全框架 1.什么是权限管理 ​ 基本上涉及到用户参与的系统都要进行权限管理&#xff0c;权限管理属于系统安全的范畴&#xff0c;权限管理实现对用户访问系统的控制&#xff0c;按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源。 权限管理…

oracle mysql postgresql opengauss 批量kill session

oracle alter system kill session sid,serial# immed; &#xff08;根据v$session中查出sid和serial#进行替换&#xff09; 这里提供一个常用脚本&#xff0c;支持跨实例kill会话 &#xff08;替换&1条件或放到脚本调用都行&#xff09; select alter system kill sessi…

Dubbo 简介

Apache Dubbo 是一款 RPC 服务开发框架&#xff0c;用于解决微服务架构下的服务治理与通信问题&#xff0c;官方提供了 Java、Golang 等多语言 SDK 实现。使用 Dubbo 开发的微服务原生具备相互之间的远程地址发现与通信能力&#xff0c; 利用 Dubbo 提供的丰富服务治理特性&…

嵌入式工程师的2022 || 2023

因为一些个人关系&#xff0c;2022年初我从北京回到了石家庄。在找工作&#xff0c;包括后续的研发工作中&#xff0c;不同地点的经历在对比中我逐渐总结出了一些经验。关于“人”方面的感悟我就不赘述了&#xff0c;下面主要在这里总结一些找工作&#xff0c;做工作的经验&…

八、迁移学习和多任务学习

文章目录1、迁移学习2、多任务学习3、端到端学习THE END1、迁移学习 \qquad迁移学习是将某个任务学习到的知识(神经网络的参数信息)迁移到另外一个相似的任务中使用&#xff0c;从而重复利用相似任务学习共同之处&#xff0c;节省模型训练的时间&#xff0c;提高模型的训练效率…

一名普通22届本科毕业生|前端程序员|22年年终总结

文章目录22年上半年&#xff1a;最后的学生时光隔离实习币基金迷茫困惑难受不要去想人生意义读书景点环境的力量再次隔离返校入职前的学习22年下半年&#xff1a;上班工作生活总结本来准备在22年年末写的&#xff0c;奈何那段时间工作太忙没抽出时间。现在是23年的1月27日&…

paddleOCR代码工程的MD模式改造

一、下载cmake_3.22.3&#xff0c;用于生成vs工程 Index of /files/v3.22 下载完成&#xff0c;解压文件&#xff0c;打开cmake-gui.exe&#xff0c;即可使用&#xff1a; 二、下载Git&#xff08;Git-2.36.0-64-bit.exe&#xff09;并按照默认路径安装&#xff0c;cmake需调用…

使用Moment格式化时间出现时间差

诶嘿&#xff0c;很离奇。前些天后端老哥给我说我这时间展示不对。 我就奇了个大怪&#xff0c;就是取的这个字段嘛&#xff0c;怎么肥事&#x1f62d; 看半天发现是时间格式化出的问题。 原代码⬇️&#xff0c;看起来没毛病嘛&#xff0c;值打印出来也与接口里的这个时间一…

到底卡在了哪里,2023年再撒谎网慢就说不过去了

前言互联网下行带来灵魂追问。钱花哪去了&#xff1f;产出在哪里&#xff1f;动辄自建的遮羞布逐步显现&#xff0c;不过自建的成本可能还不是最大的负担&#xff0c;掣肘的可能是把不重要的事情当成了主业来做&#xff0c;比如&#xff1a;互联网比如数字化转型比如研发效率和…

Verilog HDL基本语法规则

⭐本专栏针对FPGA进行入门学习&#xff0c;从数电中常见的逻辑代数讲起&#xff0c;结合Verilog HDL语言学习与仿真&#xff0c;主要对组合逻辑电路与时序逻辑电路进行分析与设计&#xff0c;对状态机FSM进行剖析与建模。 &#x1f525;文章和代码已归档至【Github仓库&#xf…

10大面试必备的排序算法 Python 实现(附源码)

今天给大家分享一篇关于Python实现排序算法的文章&#xff0c;来自GitHub。 排序算法是《数据结构与算法》中最基本的算法之一。 排序算法可以分为内部排序和外部排序&#xff0c;内部排序是数据记录在内存中进行排序&#xff0c;而外部排序是因排序的数据很大&#xff0c;一…

STM32入门基础

GPIO <1>说明 引脚电平&#xff1a;0~3.3V&#xff0c;部分可达到5V(参考引脚定义&#xff0c;带FT的就可以) 同时 GPIO有两个模式 输出模式&#xff1a;进行端口高低电平的输出&#xff0c;用于驱动LED&#xff0c;蜂鸣器等 输入模式&#xff1a;读取端口高低电平…

SimBERT剖析

SimBERT SimBERT&#xff0c;它是以Google开源的BERT模型为基础&#xff0c;基于微软的UniLM思想设计了融检索与生成于一体的任务&#xff0c;来进一步微调后得到的模型&#xff0c;所以它同时具备相似问生成和相似句检索能力。 UniLM UniLM是一个融合NLU和NLG能力的Transfo…

远程桌面控制:SmartCode VNC ViewerX ActiveX 3.10 Crack

SmartCode::ViewerX VNC 查看器 ActiveX 毫不费力地将 VNC 查看器功能添加到您的应用程序 SmartCode ViewerX VNC 查看器 ActiveX 使开发人员可以使用一组直观的 ActiveX 属性和方法完全访问 VNC 查看器功能。借助ViewerX 控件&#xff0c;开发人员可以轻松地为其应用程序提供屏…

将自己写的代码利用git 上传到码云(gitee)或者github----最简洁明了版

前置操作 注册并激活码云账号&#xff08; 注册页面地址&#xff1a;https://gitee.com/signup &#xff09; 生成并配置 SSH 公钥 官方提供的生成并配置公钥的方法点此 创建空白的码云仓库 输入仓库名称之后路径会自动生成 把本地项目上传到码云对应的空白仓库中 如果您是…

MyBatis-Plus快速开始

文章目录介绍特性框架结构传统编程模式快速开始介绍 MyBatis-Plus&#xff08;简称 MP&#xff09;是一个 MyBatis 的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。只做增强不做改变的意思是&#xff1a;MP不会影响原生的 M…