Activity 简介

Activity 类是 Android 应用的关键组件,Activity 的启动和组合方式是平台应用模型的基础部分。与通过 main() 方法启动应用的编程范式不同,Android 系统通过调用与其生命周期特定阶段对应的特定回调方法来启动 Activity 实例中的代码。

本文档介绍了 Activity 的概念,然后提供了有关如何使用它们的简单指导。有关架构应用最佳实践的更多信息,请参阅 应用架构指南

Activity 的概念

移动应用体验不同于桌面应用,用户与应用的交互并非总是从同一个地方开始。相反,用户旅程通常以不确定方式开始。例如,如果您从主屏幕打开电子邮件应用,您可能会看到一封电子邮件列表。相比之下,如果您正在使用一个社交媒体应用,然后它启动您的电子邮件应用,您可能会直接进入电子邮件应用的撰写邮件屏幕。

Activity 类的设计是为了方便这种范式。当一个应用调用另一个应用时,调用应用会调用另一个应用中的一个 Activity,而不是将整个应用作为一个原子整体。通过这种方式,Activity 充当了应用与用户交互的入口点。您将 Activity 实现为 Activity 类的子类。

Activity 提供了一个窗口,应用在此窗口中绘制其界面。此窗口通常会填充屏幕,但也可以小于屏幕并浮动在其他窗口之上。通常,一个 Activity 在一个应用中实现一个屏幕。例如,一个应用的 Activity 可能实现一个“偏好设置”屏幕,而另一个 Activity 实现一个“选择照片”屏幕。

大多数应用包含多个屏幕,这意味着它们包含多个 Activity。通常,应用中的一个 Activity 被指定为“主 Activity”,它是用户启动应用时出现的第一个屏幕。然后,每个 Activity 都可以启动另一个 Activity 以执行不同的操作。例如,一个简单的电子邮件应用中的主 Activity 可能提供显示电子邮件收件箱的屏幕。从那里,主 Activity 可能会启动其他 Activity,这些 Activity 提供诸如撰写电子邮件和打开单个电子邮件等任务的屏幕。

尽管 Activity 协同工作以在应用中形成连贯的用户体验,但每个 Activity 仅与其他 Activity 松散绑定;应用中的 Activity 之间通常只有很少的依赖关系。实际上,Activity 常常启动属于其他应用的 Activity。例如,一个浏览器应用可能会启动社交媒体应用的分享 Activity。

要在您的应用中使用 Activity,您必须在应用的清单中注册有关它们的信息,并且必须适当地管理 Activity 生命周期。

配置清单

为了让您的应用能够使用 Activity,您必须在清单中声明 Activity 及其某些属性。

声明 Activity

要声明您的 Activity,请打开清单文件,并在 <application> 元素的子级中添加一个 <activity> 元素。例如:

<manifest ... >
  <application ... >
      <activity android:name=".ExampleActivity" />
      ...
  </application ... >
  ...
</manifest >

此元素唯一必需的属性是 android:name,它指定 Activity 的类名。您还可以添加定义 Activity 特征的属性,例如标签、图标或界面主题。有关这些属性以及其他属性的更多信息,请参阅 <activity> 元素参考文档。

注意:发布应用后,不应更改 Activity 名称。如果更改,可能会破坏某些功能,例如应用快捷方式。有关发布后应避免更改的更多信息,请参阅 无法更改的事项

声明 Intent 过滤器

Intent 过滤器是 Android 平台一个非常强大的功能。它们提供了不仅基于“显式”请求,而且还基于“隐式”请求启动 Activity 的能力。例如,显式请求可能会告诉系统“启动 Gmail 应用中的发送电子邮件 Activity”。相比之下,隐式请求告诉系统“在任何可以执行此任务的 Activity 中启动发送电子邮件屏幕”。当系统界面要求用户选择使用哪个应用执行任务时,这就是 Intent 过滤器在起作用。

您可以通过在 <activity> 元素中声明一个 <intent-filter> 属性来利用此功能。此元素的定义包括一个 <action> 元素,以及可选的 <category> 元素和/或 <data> 元素。这些元素组合起来指定您的 Activity 可以响应的 Intent 类型。例如,以下代码片段展示了如何配置一个发送文本数据并接收其他 Activity 请求的 Activity:

<activity android:name=".ExampleActivity" android:icon="@drawable/app_icon">
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="text/plain" />
    </intent-filter>
</activity>

在此示例中,<action> 元素指定此 Activity 发送数据。将 <category> 元素声明为 DEFAULT 允许 Activity 接收启动请求。<data> 元素指定此 Activity 可以发送的数据类型。以下代码片段展示了如何调用上述 Activity:

Kotlin

val sendIntent = Intent().apply {
    action = Intent.ACTION_SEND
    type = "text/plain"
    putExtra(Intent.EXTRA_TEXT, textMessage)
}
startActivity(sendIntent)

Java

// Create the text message with a string
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.setType("text/plain");
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
// Start the activity
startActivity(sendIntent);
如果您希望您的应用是独立的,并且不允许其他应用激活其 Activity,则无需其他 Intent 过滤器。您不希望提供给其他应用的 Activity 不应包含任何 Intent 过滤器,您可以使用显式 Intent 自行启动它们。有关您的 Activity 如何响应 Intent 的更多信息,请参阅 Intent 和 Intent 过滤器

声明权限

您可以使用清单的 <activity> 标记来控制哪些应用可以启动特定的 Activity。父 Activity 无法启动子 Activity,除非两个 Activity 在其清单中具有相同的权限。如果您为父 Activity 声明了 <uses-permission> 元素,则每个子 Activity 都必须具有匹配的 <uses-permission> 元素。

例如,如果您的应用想使用一个名为 SocialApp 的假设应用来在社交媒体上分享帖子,那么 SocialApp 本身必须定义调用它的应用必须具有的权限:

<manifest>
<activity android:name="...."
   android:permission=”com.google.socialapp.permission.SHARE_POST”

/>

然后,为了被允许调用 SocialApp,您的应用必须匹配 SocialApp 清单中设置的权限:

<manifest>
   <uses-permission android:name="com.google.socialapp.permission.SHARE_POST" />
</manifest>

有关权限和一般安全性的更多信息,请参阅 安全性与权限

管理 Activity 生命周期

在其生命周期中,Activity 会经历许多状态。您可以使用一系列回调来处理状态之间的转换。以下各节将介绍这些回调。

onCreate()

您必须实现此回调,它在系统创建您的 Activity 时触发。您的实现应初始化 Activity 的基本组件:例如,您的应用应在此处创建视图并将数据绑定到列表。最重要的是,您必须在此处调用 setContentView() 以定义 Activity 用户界面的布局。

onCreate() 完成时,下一个回调始终是 onStart()

onStart()

onCreate() 退出时,Activity 进入“已启动”状态,并且 Activity 对用户可见。此回调包含 Activity 进入前台并变得可交互之前的最后准备工作。

onResume()

系统在 Activity 开始与用户交互之前调用此回调。此时,Activity 位于 Activity 堆栈的顶部,并捕获所有用户输入。应用的大部分核心功能都在 onResume() 方法中实现。

onPause() 回调始终在 onResume() 之后。

onPause()

当 Activity 失去焦点并进入“暂停”状态时,系统会调用 onPause()。例如,当用户点击“返回”或“最近使用”按钮时,就会出现此状态。当系统为您的 Activity 调用 onPause() 时,从技术上讲,这意味着您的 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 停止时恢复其状态。

此回调之后总是接着 onStart()

onDestroy()

系统在 Activity 被销毁之前调用此回调。

此回调是 Activity 接收到的最后一个回调。onDestroy() 通常用于确保在 Activity 或包含它的进程被销毁时,所有 Activity 的资源都得到释放。

本节仅对该主题进行了介绍。有关 Activity 生命周期及其回调的更详细论述,请参阅 Activity 生命周期