这是我参与「第四届青训营 」笔记创作活动的第2天
作为Android开发者,不可避免地要接触到Android的四大组件,因此,借着青训营的机会,整理一下有关四大组件的内容
四大组件的作用
- Activity(活动):即用户看到的界面
- Service(服务):会在后台一直运行,甚至在应用退出后,仍然能继续运行(比如打不死的广告)
- Broadcast(广播接收器):用于接收系统和其他应用发送过来的广播消息,当然,也能向系统货其他应用发送广播信息
- ContentProvider(内容提供者):应用之间数据交互的桥梁,为数据提供了供外界访问的各种接口
Activity
关于Activity的主要内容,主要就围绕三个方面转,分别为:生命周期、启动模式、碎片(Fragment)
生命周期
onCreate():在系统首次创建 Activity 时触发,该回调结束后, Activity 进入“已开始”,状态,之后会调用onStart()方法,一般在此处创建视图和进行数据绑定onStart():当 Activity 进入“已开始”状态时,系统会调用此回调。可以在此为 Activity 进入前台并支持互动做准备,即让 Activity 由不可见状态变为可见状态。例如,应用通过此方法来初始化维护界面的代码。回调结束之后,Activity 进入“已恢复” 状态,之后会调用onResume()onResume():处于运行状态时调用,用户可进行触碰点击页面上的各种组件,从而与活动进行交互,直到 Activity 失去焦点onPause():当前 Activity 去启动其他活动时调用onStop():Activity 处于完全不可见状态就调用onDestroy():Activity 销毁前调用,调用之后 Activity 就会被销毁,释放该 Activity 的所有资源onRestart():当 Activity 重新被启动时调用,由停止状态变为可见状态,然后继续运行onSaveInstanceState():在非正常关闭时回调,用于保存数据,不支持持久化数据onRestoreInstanceState()/onCreate():用于恢复数据
启动模式
-
如何设置:
- 第一种方法:在配置文件 AndroidManifest.xml 里用 android:launchMode 来指定,分别可以指定为
standard、singleTop、singleTask和singleInstance - 第二种方法:在 Intent 中设置标记 flag 来指定启动模式
- 第一种方法:在配置文件 AndroidManifest.xml 里用 android:launchMode 来指定,分别可以指定为
-
standard:
- 默认的启动模式,每次启动一个活动时,就会创建一个实例,并运行在启动该活动的活动栈的栈顶
- 允许 Activity 被重复创建
-
singleTop
- 如果任务栈栈顶中存在该 Activity 实例,则直接复用,并会调用
onNewIntent()方法;如果没有则会创建新的实例并且入栈到栈顶。 - 不允许连续重复
- 如果任务栈栈顶中存在该 Activity 实例,则直接复用,并会调用
-
singleTask
- 与 singleTop 不同,该启动方式,只要任务栈中存在该 Activity 实例,就会将该目标 Activity 上方的所有实例出栈,然后复用栈中的该实例。如果不存在,则会直接创建,并加入栈顶。
- 不允许同个栈内重复
-
singleInstance
- 创建一个新的任务栈来专门存储和管理该 Activity 的事务,并且会确保该 Activity 具有全局唯一性,也就是任何应用只要启动该 Activity,用的都是该实例
- 整个系统不允许重复
Fragment
- 与 Activity 类似,也可以显示各种组件与布局的页面,也能进行嵌套,使用起来灵活性更高,便于复用,主要作用是为笨重的 Activity 引入模块化和可复用性,可以理解为缩小版的 Activity
- Fragment 的生命周期与 Activity 类似,下面给出其基本流程图:
Service
Service 即 Android 中的服务,主要可以从其生命周期和类型进行了解
生命周期
| 方法 | 含义 |
|---|---|
| onCreate() | 首次创建服务时,系统将调用此方法。 |
| onStartCommand() | 当另一个组件通过调用请求启动服务时,系统将调用此方法 |
| onDestroy() | 当服务不再使用且将被销毁时,系统将调用此方法 |
| onBind() | 当另一个组件通过调用 bindService() 与服务绑定时,系统将调用此方法。 |
| onUnbind() | 当另一个组件通过调用 unbindService() 与服务解绑时,系统将调用此方法。 |
| onRebind() | 当旧的组件与服务解绑后,另一个新的组件与服务绑定 onUnbind(),返回true时,系统将调用此方法。 |
- 下面是 Service 生命周期的流程图:
类型
-
普通 Service
- 没有特别声明,一般创建的就是普通的Service,启动是方式有 startService() 和bindService()
-
前台 Service
- 可以一直运行,不会被系统回收,比如:在手机状态栏显示的应用的图标,其实就是开启了 前台Service。
- 需要在 manifest 文件中声明权限:
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/> -
意图 Service
- IntentService,由于服务默认运行在主线程,所以如果直接使用它来处理一些耗时操作,会很容易出现 ANR 问题,所以此时可以使用 IntentService,它可以说是一般服务的升级版,继承自 Service,相比于一般 Service,它有独立的线程来处理 Intent 请求和各种耗时的操作,所以不用开发者自己动手创建线程。另外,当处理完所有请求后,它 会自动停止,所以也不用自己动手调用 stopService() 方法
注意事项
- 每个 Service 都只存在一个实例,所以要停止 Service 时,只需要调用一次 stopService(),不管调用了多少次 startService() 方法
- 要实现 Activity 与 Service 交互,只需要在 Activity 中调用 bindService() 方法,就可以获取 Service 的 onBind() 里返回的 IBinder对象实例
- 当要停止 Service 时,可以调用 unbindService() 方法,其 onDestroy() 就会被自动执行
- 如果同时调用了 startService() 与 bindService() 方法,那么在停止 Service 时,就需要同时调用 stopService() 与 unbindService()
Broadcast
用于接收系统和其他应用发来的广播,也可以向其他应用或系统发送广播,分为发送和接收两端
类型
-
普通 Broadcast
- 一种完全异步的 Broadcast,发出之后,所有 BroadcastReceiver 都能在同一时刻接收到该 Broadcast 的信息;
- 优点:传递效率非常高
- 缺点:安全性不能保证,因为 BroadcastReceiver 不能拦截信息,这意味着所有的应用都可以无差别获得 Broadcast 的信息,显然这并不安全
-
有序 Broadcast
-
一种同步执行的 Broadcast,所以该 Broadcast 发出后,同一时刻只有一个 BroadcastReceiver 可以接收到该 Broadcast 的信息,并且还能进行拦截,当然也可以不进行拦截,这样就会顺次向下传递,类似于一个 filter 的作用
-
既然是有序的,那就意味着有优先级,BroadcastReceiver 的优先级可以在其 intent-filter 元素的 android-priority 属性中设置优先级,数越大,则优先级更高,取值范围为 [-1000,1000]。
-
注意:
- 如果优先级相同,则动态注册的 BroadcastReceiver 优先于静态注册的
- 如果优先级和注册类型都相同,则按注册顺序决定谁先接收
-
-
本地 Broadcast
- 不同于普通 Broadcast 与 有序 Broadcast 可以被其他应用接收,本地 Broadcast 发出的信息只能在一个应用内进行传播,所以定义的 BroadcastReceiver 也只能接收来自该应用发出的 Broadcast 信息
- 优点:安全性得到保证,因为其他的应用无法接收到信息
如何发送
-
发送普通 Broadcast
Intent intent = new Intent("action");
sendBroadcast(intent);
通过定义 intent 的 action 来区分每条 Broadcast,然后可以给自定义的 BroadcastReceiver 设置能匹配的 action,当 Broadcast 一发出去,就能进行匹配从而实现接收指定的 Broadcast
-
发送有序 Broadcast
Intent intent = new Intent("action");
sendOrderedBroadcast(intent,null);
如果需要指定优先级,可以在注册 BroadcastReceiver 的时候,在其 intent-filter 元素的 android-priority 属性中设置优先级,数越大,则优先级更高,取值范围为 [-1000,1000]。
-
发送本地 Broadcast
Intent intent = new Intent("action");
localBroadcastManager.sendBroadcast(intent);
依托于 localBroadcastManager 来进行发送、注册与注销
ContentProvider
对要共享给其他应用的数据创建了外部访问接口,其他应用只需调用这些接口就能访问到要交互的数据了
分类
-
系统 ContentProvider
-
对于系统已经封装实现的 ContentProvider (通讯录、短信等),我们不需要关心其具体实现,就可以直接使用:
- 获取 ContentResolver 实例:getContentResolver()
- 解析 Uri:Uri.parse('内容 Uri')
- 调用增删改查方法:跟 SQLite 数据库的增删改查方法类似
-
自定义 ContentProvider
-
将自定义的 ContentProvider 继承自 ContentProvider 类,然后重写以下抽象方法:
- onCreate()
- query()
- insert()
- update()
- delete()
- getType()