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

如需声明 activity,请打开清单文件,并添加 <activity> 元素作为 <application> 元素的子元素。例如:

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

此元素唯一的必需属性是 android:name,用于指定 activity 的类名称。您还可以添加用于定义标签、图标或界面主题等 activity 特性的属性。如需详细了解这些属性和其他属性,请参阅 <activity> 元素参考文档。

注意 :发布应用后,不应更改 activity 名称。否则可能会破坏某些功能,例如应用快捷方式。如需详细了解发布后应避免的更改,请参阅 无法更改的内容

声明 intent 过滤器

intent 过滤器是 Android 平台的一项非常强大的功能。它们不仅能够基于显式请求启动 activity,还能基于隐式请求启动 activity。例如,显式请求可能会告知系统“在 Gmail 应用中启动‘发送电子邮件’activity”。相比之下,隐式请求会告知系统“在任何可以执行此操作的 activity 中启动‘发送电子邮件’屏幕”。当系统界面询问用户使用哪个应用来执行任务时,这就是 intent 过滤器在起作用。

您可以通过在 <activity> 元素中声明 <intent-filter> 属性来利用此功能。此元素的定义包括 <action> 元素,以及可选的 <category> 元素和/或 <data> 元素。这些元素组合在一起,可指定您的 activity 可以响应的 intent 类型。例如,以下代码段展示了如何配置一个用于发送文本数据并接收来自其他 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 进入前台并进入可交互状态所需的最后准备工作。

onResume()

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

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

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 停止时恢复其状态。

此回调后跟 onStart()

onDestroy()

系统会在销毁 activity 之前调用此回调。

此回调是 activity 接收的最后一个回调。 通常,实现 onDestroy() 可确保在 activity 或包含该 activity 的进程被销毁时释放 activity 的所有资源。

本部分只是简要地介绍了该主题。如需详细了解 activity 生命周期及其回调,请参阅 activity 生命周期