Android 打卡 Day3 - 四大组件 - 初识


Android 平台架构

Android 是一个适用于移动设备的开源操作系统,由 Google 主导对应的开源项目。整个 Android 以 Linux 的核心作为底层,加上中介函数库和 API,函数库大部分以 C语言设计,框架大多以 Java 相容的程序编写,在这个框架之上才是手机安装的应用。作为一个开源项目,Android 被打造成了一个适用于消费类产品的完整高品质操作系统,并配有可自定义并运用到几乎所有设备的源代码,以及所有用户均可使用的公开文档。

从下往上:

  • Linux 内核。

  • HAL - 硬件抽象层。提供标准界面,向更高级别的 Java API 框架显示设备硬件功能。HAL 包含多个库模块,其中每个模块都为特定类型的硬件组件实现一个界面,例如相机或蓝牙模块。当框架 API 要求访问设备硬件时,Android 系统将为该硬件组件加载库模块。

  • ART - Android Runtime。

  • 原生 C/C++ 库 - 许多核心 Android 系统组件和服务(例如 ART 和 HAL)构建自原生代码,需要以 C 和 C++ 编写的原生库。Android 平台提供 Java 框架 API 以向应用显示其中部分原生库的功能。

  • Java API 框架- 可通过以 Java 语言编写的 API 使用 Android OS 的整个功能集。这些 API 形成创建 Android 应用所需的构建块,它们可简化核心模块化系统组件和服务的重复使用,包括以下组件和服务:

    • 丰富、可扩展的视图系统,可用以构建应用的 UI,包括列表、网格、文本框、按钮甚至可嵌入的网络浏览器
    • 资源管理器,用于访问非代码资源,例如本地化的字符串、图形和布局文件
    • 通知管理器,可让所有应用在状态栏中显示自定义提醒
    • Activity 管理器,用于管理应用的生命周期,提供常见的导航返回栈
    • 内容提供程序,可让应用访问其他应用(例如“联系人”应用)中的数据或者共享其自己的数据

    开发者可以完全访问 Android 系统应用使用的框架 API

  • 系统应用(System Apps)- 相机、邮件、短信、日历等。

四大组件

☄️ Activity

  • 一个 Activity 通常就是一个单独的屏幕(窗口)。此窗口通常会填满屏幕,但也可能比屏幕小,并浮动在其他窗口上面。通常,应用中的一个 Activity 会被指定为主 Activity,这是用户启动应用时出现的第一个屏幕。然后,每个 Activity 可以启动另一个 Activity,以执行不同的操作。例如,一个简单的电子邮件应用中的主 Activity 可能会提供显示电子邮件收件箱的屏幕。主 Activity 可能会从该屏幕启动其他 Activity,以提供执行写邮件和打开邮件这类任务的屏幕。

  • Activity 之间通过 Intent 进行通信。虽然应用中的各个 Activity 协同工作形成统一的用户体验,但每个 Activity 与其他 Activity 之间只存在松散的关联,应用内不同 Activity 之间的依赖关系通常很小。事实上,Activity 经常会启动属于其他应用的 Activity。例如,浏览器应用可能会启动社交媒体应用的“分享”Activity。

  • Android 应用中每一个 Activity 都必须要在 AndroidManifest.xml 配置文件中声明,并且必须适当地管理 Activity 的生命周期,否则系统将不识别也不执行该 Activity。

  • 使用 <activity> 标签进行声明,唯一的必要属性是 android:name

  • 使用 Intent 显示/隐式请求启动 Activity。

  • 生命周期:

    onCreate() 在系统创建 Activity 时触发,初始化 Activity 的基本组件、必须在此处调用 setContentView() 来定义 Activity 界面的布局。
    ⬇️
    onStart() “已启动”,并对用户可见。此回调包含 Activity 进入前台与用户进行互动之前的最后准备工作。
    ⬇️
    onResume() 系统会在 Activity 开始与用户互动之前调用此回调。此时,该 Activity 位于 Activity 堆栈的顶部,并会捕获所有用户输入。应用的大部分核心功能都是在 onResume() 方法中实现的。onResume() 回调后面总是跟着 onPause() 回调。
    ⬇️
    onPause() 当 Activity 失去焦点并进入“已暂停”状态时,系统就会调用 onPause()。例如,当用户点按“返回”或“最近使用的应用”按钮时,就会出现此状态。当系统调用 Activity 的 onPause() 时,从技术上来说,这意味着该 Activity 仍然部分可见,但大多数情况下,这表明用户正在离开该 Activity,该 Activity 很快将进入“已停止”或“已恢复”状态。如果用户希望界面继续更新,则处于“已暂停”状态的 Activity 也可以继续更新界面。例如,显示导航地图屏幕或播放媒体播放器的 Activity 就属于此类 Activity。即使此类 Activity 失去了焦点,用户仍希望其界面继续更新。开发者应使用 onPause() 来保存应用或用户数据、进行网络呼叫或执行数据库事务。有关保存数据的信息,请参阅保存和恢复 Activity 状态

    onPause() 执行完毕后,下一个回调为 onStop()onResume(),具体取决于 Activity 进入“已暂停”状态后发生的情况。
    ⬇️
    onStop() 当 Activity 对用户不再可见时,系统会调用 onStop()。出现这种情况的原因可能是 Activity 被销毁、新的 Activity 启动、或者现有的 Activity 正在进入“已恢复”状态并覆盖了已停止的 Activity。在所有这些情况下,停止的 Activity 都将完全不再可见。系统调用的下一个回调将是 onRestart()(如果 Activity 重新与用户互动)或者 onDestroy()(如果 Activity 彻底终止)。

    ⬇️
    onRestart() 当处于“已停止”状态的 Activity 即将重启时,系统就会调用此回调。onRestart() 会从 Activity 停止时的状态恢复 Activity。此回调后面总是跟着 onStart()
    ⬇️
    onDestroy() 系统会在销毁 Activity 之前调用此回调。此回调是 Activity 接收的最后一个回调。通常,实现 onDestroy() 是为了确保在销毁 Activity 或包含该 Activity 的进程时释放该 Activity 的所有资源。

生命周期整体上和 iOS 类似。

☄️ Service

  • Service 是一种可在后台执行长时间运行操作而不提供界面的应用组件。Service 可由其他应用组件启动,而且即使用户切换到其他应用,Service 仍将在后台继续运行。此外,组件可通过绑定到 Service 与之进行交互,甚至是执行进程间通信 (IPC)。Service 组件通常用于为其他组件提供后台服务或监控其他组件的运行状态,例如,服务可在后台处理网络事务、播放音乐,执行文件 I/O 或与内容提供程序进行交互。

  • Service 的启动方式分为两种:

    • Started(启动):当应用程序组件(如 activity)调用 startService() 方法启动服务时,服务处于 started 状态。
    • Bound(绑定):当应用程序组件调用 bindService() 方法绑定到服务时,服务处于 bound 状态。
  • startService() 与 bindService() 区别:

    • Started Service(启动服务)是由其他组件调用 startService() 方法启动的,这导致服务的 onStartCommand() 方法被调用。当服务是 started 状态时,其生命周期与启动它的组件无关,并且可以在后台无限期运行,即使启动服务的组件已经被销毁。因此,服务需要在完成任务后调用 stopSelf() 方法停止,或者由其他组件调用 stopService() 方法停止。
    • Bound Service(绑定服务)使用 bindService() 方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,“不求同年同月同日生,必须同年同月同日死”。
  • 如同 Activity 及其他组件的操作一样,开发者必须在 AndroidManifest.xml 文件中声明所有服务,使用 标签。

  • 生命周期:

    左图显示使用 startService() 创建的服务的生命周期,右图显示使用 bindService() 创建的服务的生命周期,两者还可以嵌套循环使用。

☄️ Content Provider

  • Content Provider 使一个应用程序的指定数据集提供给其他应用程序,是一种标准接口。其他应用可以通过 ContentResolver 类从该内容提供者中访问或修改数据。
  • 只有需要在多个应用程序间共享数据是才需要内容提供者。例如,通讯录数据被多个应用程序使用,且必须存储在一个内容提供者中。它的好处是统一数据访问方式。
  • ContentProvider 实现数据共享。ContentProvider 用于保存和获取数据,并使其对所有应用程序可见。这是不同应用程序间共享数据的唯一方式,因为 Android 没有提供所有应用共同访问的公共存储区。
  • 开发人员不会直接使用 ContentProvider 类的对象,大多数是通过 ContentResolver 对象实现对 ContentProvider 的操作。
  • ContentProvider 使用 URI 来唯一标识其数据集,这里的 URI 以 content:// 作为 scheme,表示该数据由 ContentProvider 来管理。

☄️ Broadcast Receiver

  • 类似发布-订阅的设计模式,应用可以订阅特定的广播,对外部事件进行过滤,只对感兴趣的外部事件 (如当电话呼入时,或者数据网络可用时) 进行接收并做出响应。广播接收器没有用户界面。然而,它们可以启动一个 Activity 或 Service 来响应它们收到的信息,或者用 NotificationManager 来通知用户,通知可以用很多种方式来吸引用户的注意力,例如闪动背灯、震动、播放声音等。一般来说是在状态栏上放一个持久的图标,用户可以打开它并获取消息。
  • 应用可以通过两种方式接收广播:清单声明的(静态)接收器和上下文注册的(动态)接收器。
  • 动态注册广播接收器特点是当用来注册的 Activity 关掉后,广播也就失效了。静态注册无需担忧广播接收器是否被关闭,只要设备是开启状态,广播接收器也是打开着的。也就是说即使 App 本身未启动,该 app 订阅的广播在触发时也会对它起作用。

🔆 概念理解起来还算顺利,Activity 类似 ViewController,Content Provider 一定程度上类似文件分享?,Broadcast 类似 iOS 的远程/本地通知,还有 Service 和 iOS 的小组件有点类似,但是限制明显比 iOS 少一些…

Demo

仅用于记录学习过程,不具备指导性。🤓

Demo-Github


下一日目标:Demo 中实践四大组件。