Activity是Android开发中最重要的组件,我们大部分时间都在和Activity打交道,我们可以把Activity和Web的页面进行类比,Web页面上有很多标签,Activity则包含各种控件。
一个应用通常由多个彼此松散联系的 Activity 组成。 一般会指定应用中的某个 Activity 为“主”Activity,即首次启动应用时呈现给用户的那个 Activity。 而且每个 Activity 均可启动另一个 Activity,以便执行不同的操作。
下面,我们开发一个Activity
开发一个Activity
要创建 Activity,必须创建 Activity 的子类(或使用其现有子类)。Activity类的继承关系如下图所示:
当我们通过Android Studio创建一个Android项目时,选择Empty Activity,如下所示:
系统会为我们创建包含了一个Activity的项目,如下图所示:
并且会在清单文件中对Activity进行配置,配置信息如下图所示:
我们可以通过File->New->Activity创建新的Activity,如下图所示:
例如我们新创建了一个SettingActivity,如下图所示:
系统会为我们创建Activity基本代码,并在清单文件中进行了配置。
下面我们先学习一下Activity的配置信息。
注意:新建Activity时,如果勾选Backwards Compatibility(AppCompat),新创建的Activity会从AppCompatActivity继承,如果不勾选,则新建的Activity直接从Activity继承。AppCompatActivity作为Activity的子类,关于他的介绍,后面课程会有详细的说明。
Activity的配置信息
Activity需要在清单文件中进行配置,所有 Activity 都必须由清单文件中的 <activity> 元素表示。 任何未在该处声明的 Activity 都将对系统不可见,并且也永远不会被运行。
<activity>标签的包含在<application>标签中,包括如下属性
<activity android:allowEmbedded=["true" | "false"] android:allowTaskReparenting=["true" | "false"] android:alwaysRetainTaskState=["true" | "false"] android:autoRemoveFromRecents=["true" | "false"] android:banner="drawable resource" android:clearTaskOnLaunch=["true" | "false"] android:configChanges=["mcc", "mnc", "locale", "touchscreen", "keyboard", "keyboardHidden", "navigation", "screenLayout", "fontScale", "uiMode", "orientation", "screenSize", "smallestScreenSize"] android:documentLaunchMode=["intoExisting" | "always" | "none" | "never"] android:enabled=["true" | "false"] android:excludeFromRecents=["true" | "false"] android:exported=["true" | "false"] android:finishOnTaskLaunch=["true" | "false"] android:hardwareAccelerated=["true" | "false"] android:icon="drawable resource" android:label="string resource" android:launchMode=["standard" | "singleTop" | "singleTask" | "singleInstance"] android:maxRecents="integer" android:multiprocess=["true" | "false"] android:name="string" android:noHistory=["true" | "false"] android:parentActivityName="string" android:permission="string" android:process="string" android:relinquishTaskIdentity=["true" | "false"] android:resizeableActivity=["true" | "false"] android:screenOrientation=["unspecified" | "behind" | "landscape" | "portrait" | "reverseLandscape" | "reversePortrait" | "sensorLandscape" | "sensorPortrait" | "userLandscape" | "userPortrait" | "sensor" | "fullSensor" | "nosensor" | "user" | "fullUser" | "locked"] android:stateNotNeeded=["true" | "false"] android:supportsPictureInPicture=["true" | "false"] android:taskAffinity="string" android:theme="resource or theme" android:uiOptions=["none" | "splitActionBarWhenNarrow"] android:windowSoftInputMode=["stateUnspecified", "stateUnchanged", "stateHidden", "stateAlwaysHidden", "stateVisible", "stateAlwaysVisible", "adjustUnspecified", "adjustResize", "adjustPan"] > . . . </activity> |
在<activity>标签中,还可以包含<intent-filter> 、<meta-data>。
下面我们给出activity标签属性的详细说明
- android:allowEmbedded
表示该 Activity 可作为另一 Activity 的嵌入式子项启动。 它尤其适用于子项所在的容器为另一 Activity 所拥有的情况。 例如,用于 Wear 自定义notification的 Activity 必须声明此项,以便 Wear 在其上下文流中显示 Activity,后者位于另一进程中。
该属性的默认值为 false。
- android:allowTaskReparenting
当启动 Activity,Activity 是否能从该任务转移至与其有亲和关系的任务 —“true”表示它可以转移,“false”表示它仍须留在启动它的任务栈中。
如果未设置该属性,则对 Activity 应用由 <application> 元素的相应 allowTaskReparenting 属性设置的值。 默认值为“false”。
- android:alwaysRetainTaskState
系统是否始终保持 Activity 所在任务的状态 —“true”表示保持,“false”表示允许系统在特定情况下将任务重置到其初始状态。 默认值为“false”。该属性只对任务的根 Activity 有意义;对于所有其他 Activity,均忽略该属性。
- android:autoRemoveFromRecents
由具有该属性的 Activity 启动的任务是否一直保留在概览屏幕中,直至任务中的最后一个 Activity 完成为止。若为 true,则自动从概览屏幕中移除任务。
概览屏幕(也称为最新动态屏幕、最近任务列表或最近使用的应用)是一个系统级别 UI,其中列出了最近访问过的 Activity 和任务。 用户可以浏览该列表并选择要恢复的任务,也可以通过滑动清除任务将其从列表中移除。
- android:banner
一种为其关联项提供扩展图形化横幅的可绘制资源。 将其与 <activity> 标记联用可为特定 Activity 提供默认横幅,也可与 <application> 标记联用,为所有应用 Activity 提供横幅。
系统使用横幅在 Android TV 主屏幕中表示应用。 由于横幅只显示在主屏幕中,因此只应由包含的 Activity 能够处理 CATEGORY_LEANBACK_LAUNCHER Intent 的应用指定。
必须将该属性设置为对包含图像的可绘制资源的引用(例如 "@drawable/banner")。 没有默认横幅。
- android:clearTaskOnLaunch
是否每当从主屏幕重新启动任务时都从中移除根 Activity 之外的所有 Activity —“true”表示始终将任务清除到只剩其根 Activity;“false”表示不做清除。 默认值为“false”。该属性只对启动新任务的 Activity(根 Activity)有意义;对于任务中的所有其他 Activity,均忽略该属性。
- android:configChanges
列出 Activity 将自行处理的配置更改。在运行时发生配置更改时,默认情况下会关闭 Activity 然后将其重新启动,但使用该属性声明配置将阻止 Activity 重新启动。 Activity 反而会保持运行状态,并且系统会调用其 onConfigurationChanged() 方法。
注:应避免使用该属性,并且只应在万不得已的情况下使用。
- android:documentLaunchMode
指定每次启动任务时应如何向其中添加新的 Activity 实例。 该属性允许用户让多个来自同一应用的文档出现在概览屏幕中。
- android:enabled
系统是否可将 Activity 实例化 — "true" 表示可以,“false”表示不可以。 默认值为“true”。
<application> 元素具有自己的 enabled 属性,该属性适用于所有应用组件,包括 Activity。 <application> 和 <activity> 属性必须都是“true”(因为它们都默认使用该值),系统才能将 Activity 实例化。 如果任何一个属性是“false”,则无法进行实例化。
- android:excludeFromRecents
是否应将该 Activity 启动的任务排除在最近使用的应用列表(即概览屏幕)之外。 也就是说,当该 Activity 是新任务的根 Activity 时,此属性确定任务是否应出现在最近使用的应用列表中。 如果应将任务排除在列表之外,请设置“true”;如果应将其包括在内,则设置“false”。 默认值为“false”。
- android:exported
Activity 是否可由其他应用的组件启动 —“true”表示可以,“false”表示不可以。若为“false”,则 Activity 只能由同一应用的组件或使用同一用户 ID 的不同应用启动。
默认值取决于 Activity 是否包含 Intent 过滤器。没有任何过滤器意味着 Activity 只能通过指定其确切的类名称进行调用。 这意味着 Activity 专供应用内部使用(因为其他应用不知晓其类名称)。 因此,在这种情况下,默认值为“false”。另一方面,至少存在一个过滤器意味着 Activity 专供外部使用,因此默认值为“true”。
- android:finishOnTaskLaunch
每当用户再次启动其任务(在主屏幕上选择任务)时,是否应关闭(完成)现有 Activity 实例 —“true”表示应关闭,“false”表示不应关闭。 默认值为“false”。
如果该属性和 allowTaskReparenting 均为“true”,则优先使用该属性。 Activity 的亲和关系会被忽略。系统不是更改 Activity 的父项,而是将其销毁。
- android:hardwareAccelerated
是否应为此 Activity 启用硬件加速渲染 —“true”表示应启用,“false”表示不应启用。 默认值为“false”。
从 Android 3.0 开始,为应用提供了硬件加速 OpenGL 渲染器,以改善许多常见 2D 图形运算的性能。 启用硬件加速渲染器时,Canvas、Paint、Xfermode、ColorFilter、Shader 和 Camera 中的大多数运算都会得到加速。这可以提高动画、滚动的流畅度和总体响应速度,即便是并不明确使用框架 OpenGL 库的应用也会受益。 由于启用硬件加速会增加资源消耗,因此您的应用将占用更多内存。
请注意,并非所有 OpenGL 2D 运算都会得到加速。如果您启用硬件加速渲染器,请对应用进行测试,以确保其在利用渲染器时不会出错。
- android:icon
一个表示 Activity 的图标。该图标会在需要在屏幕上表示 Activity 时显示给用户。
必须将该属性设置为对包含图像定义的可绘制资源的引用。 如果未设置该属性,则改为使用为应用整体指定的图标。
这个 Activity 的图标 — 无论设置于此处还是由 <application> 元素设置 — 同时也是 Activity 所有 Intent 过滤器的默认图标(请参阅 <intent-filter> 元素的 icon 属性)。
- android:label
一种可由用户读取的 Activity 标签。该标签会在必须将 Activity 呈现给用户时显示在屏幕上。 它通常与 Activity 图标一并显示。
如果未设置该属性,则改为使用为应用整体设置的标签。
这个 Activity 的标签 — 无论设置于此处还是由 <application> 元素设置 — 同时也是 Activity 所有 Intent 过滤器的默认标签。
- android:launchMode
有关应如何启动 Activity 的指令。共有四种模式与 Intent 对象中的 Activity 标志(FLAG_ACTIVITY_* 常量)协同工作,以确定在调用 Activity 处理 Intent 时应执行的操作。
- android:multiprocess
是否可以将 Activity 实例启动到启动该实例的组件进程内 —“true”表示可以,“false”表示不可以。默认值为“false”。正常情况下,新的 Activity 实例会启动到定义它的应用进程内,因此所有 Activity 实例都在同一进程内运行。 不过,如果该标志设置为“true”,Activity 实例便可在多个进程内运行,这样系统就能在任何使用实例的地方创建实例(前提是权限允许这样做),但这几乎毫无必要性或可取之处。
- android:name
实现 Activity 的类的名称,是 Activity 的子类。 该属性值应为完全限定类名称(例如,“com.example.project.ExtracurricularActivity”)。不过,为了简便起见,如果名称的第一个字符是句点(例如,“.ExtracurricularActivity”),则名称将追加到 <manifest> 元素中指定的软件包名称。
- android:noHistory
当用户离开 Activity 并且其在屏幕上不再可见时,是否应从 Activity 堆栈中将其移除并完成(调用其 finish() 方法)—“true”表示应将其完成,“false”表示不应将其完成。 默认值为“false”。
“true”一值表示 Activity 不会留下历史轨迹。 它不会留在任务的 Activity 堆栈内,因此用户将无法返回 Activity。在此情况下,如果您启动另一个 Activity 来获取该 Activity 的结果,系统永远不会调用 onActivityResult()。
- android:parentActivityName
Activity 逻辑父项的类名称。此处的名称必须与为相应 <activity> 元素的 android:name 属性指定的类名称一致。系统会读取该属性,以确定当用户按下操作栏中的“返回”按钮时应该启动哪一个 Activity。
如下图设置
点击返回按钮后,系统返回MainActivity。
注意,要支持 API 级别 4 - 16,可以使用为 "android.support.PARENT_ACTIVITY" 指定值的 <meta-data> 元素来声明父 Activity,如下代码所示:
<activity android:name="com.example.app.ChildActivity" android:label="@string/title_child_activity" android:parentActivityName="com.example.app.MainActivity" > <!-- Parent activity meta-data to support API level 4+ --> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value="com.example.app.MainActivity" /> </activity> |
- android:permission
客户端启动 Activity 或以其他方式令其响应 Intent 而必须具备的权限的名称。
- android:process
应在其中运行 Activity 的进程名称。正常情况下,应用的所有组件都在为应用创建的默认进程名称内运行,无需使用该属性。可以使用该属性替换默认进程名称,以便让应用组件散布到多个进程中。
- android:relinquishTaskIdentity
Activity 是否将其任务标识符交给任务栈中在其之上的 Activity。 如果任务根 Activity 的该属性设置为“true”,则任务会用其内的下一个 Activity 的 Intent 替换基本 Intent。 如果下一个 Activity 的该属性也设置为“true”,则该 Activity 会将基本 Intent 给予其在同一任务中启动的任何 Activity。系统继续为每个 Activity 执行此过程,直至遇到的某个 Activity 将该属性设置为“false”为止。 默认值为“false”。
如果该属性设置为“true”,则 Activity 还可利用 ActivityManager.TaskDescription 来更改概览屏幕中的标签、颜色和图标。
- resizeableActivity
指定应用是否支持多窗口显示。可以在 <activity> 或 <application> 元素中设置该属性。
- android:screenOrientation
Activity 在设备上的显示方向。如果 Activity 是在多窗口模式下运行,系统会忽略该属性。
该属性的取值及意义如下表所示:
值 | 说明 |
“unspecified” | 默认值。由系统选择方向。在不同设备上,系统使用的政策以及基于政策在特定上下文所做的选择可能有所差异。 |
“behind” | 与 Activity 栈中紧接着它的 Activity 的方向相同。 |
“landscape” | 横向方向(显示的宽度大于高度)。 |
“portrait” | 纵向方向(显示的高度大于宽度)。 |
“reverseLandscape” | 与正常横向方向相反的横向方向。API 级别 9 中的新增配置。 |
“reversePortrait” | 与正常纵向方向相反的纵向方向。API 级别 9 中的新增配置。 |
“sensorLandscape” | 横向方向,但根据设备传感器,可以是正常或反向的横向方向。API 级别 9 中的新增配置。 |
“sensorPortrait” | 纵向方向,但根据设备传感器,可以是正常或反向的纵向方向。API 级别 9 中的新增配置。 |
“userLandscape” | 横向方向,但根据设备传感器和用户的传感器首选项,可以是正常或反向的横向方向。 如果用户锁定了基于传感器的旋转,其行为与 landscape 相同,否则,其行为与 sensorLandscape 相同。API 级别 18 中的新增配置。 |
“userPortrait” | 纵向方向,但根据设备传感器和用户的传感器首选项,可以是正常或反向的纵向方向。 如果用户锁定了基于传感器的旋转,其行为与 portrait 相同,否则,其行为与 sensorPortrait 相同。API 级别 18 中的新增配置。 |
“sensor” | 方向由设备方向传感器决定。显示方向取决于用户如何手持设备,它会在用户旋转设备时发生变化。 但一些设备默认情况下不会旋转到所有四种可能的方向。要允许全部四种方向,请使用 "fullSensor"。 |
“fullSensor” | 方向由 4 种方向中任一方向的设备方向传感器决定。这与 "sensor" 类似,不同的是它允许所有 4 种可能的屏幕方向,无论设备正常情况下采用什么方向(例如,一些设备正常情况下不使用反向纵向或反向横向,但它支持这些方向)。 API 级别 9 中的新增配置。 |
“nosensor” | 决定方向时不考虑物理方向传感器。传感器会被忽略,因此显示不会随用户对设备的移动而旋转。 除了这个区别,系统在选择方向时使用的政策与“unspecified”设置相同。 |
“user” | 用户当前的首选方向。 |
"fullUser" | 如果用户锁定了基于传感器的旋转,其行为与 user 相同,否则,其行为与 fullSensor 相同,允许所有 4 种可能的屏幕方向。 API 级别 18 中的新增配置。 |
“locked” | 将方向锁定在其当前的任意旋转方向。API 级别 18 中的新增配置。 |
- android:stateNotNeeded
能否在不保存 Activity 状态的情况下将其终止并成功重新启动 —“true”表示可在不考虑其之前状态的情况下重新启动,“false”表示需要之前状态。 默认值为“false”。
正常情况下,为保存资源而暂时关闭 Activity 前,系统会调用其 onSaveInstanceState() 方法。 该方法将 Activity 的当前状态存储在一个 Bundle 对象中,然后在 Activity 重新启动时将其传递给 onCreate()。 如果该属性设置为“true”,系统可能不会调用 onSaveInstanceState(),并且会向 onCreate() 传递 null 而不是 Bundle - 这与它在 Activity 首次启动时完全一样。
“true”设置可确保 Activity 能够在未保留状态时重新启动。例如,显示主屏幕的 Activity 可以使用该设置来确保其由于某种原因崩溃时不会被移除。
- supportsPictureInPicture
指定 Activity 是否支持画中画 显示。如果 android:resizeableActivity 是 false,系统会忽略该属性。在 Android N 中,Android TV 用户现在可以一边在应用中导航一边在屏幕角落的固定窗口中观看视频。 画中画 (PIP) 模式允许应用在固定窗口中运行视频 Activity,同时在后台继续运行另一个 Activity。 PIP 窗口让用户可以在使用应用的时候进行多任务处理,从而提高效率。
- android:taskAffinity
与 Activity 有着亲和关系的任务。从概念上讲,具有相同亲和关系的 Activity 归属同一任务(从用户的角度来看,则是归属同一“应用”)。 任务的亲和关系由其根 Activity 的亲和关系确定。
- android:theme
对定义 Activity主题的样式资源的引用。它会自动将 Activity 的上下文设置为使用该主题, 如果未设置该属性,则 Activity 继承通过 <application> 元素的 theme 属性为应用整体设置的主题。
- android:uiOptions
针对 Activity UI 的附加选项。必须是下列值之一。
值 | 说明 |
"none" | 无附加 UI 选项。这是默认值。 |
"splitActionBarWhenNarrow" | 当水平空间受限时(例如在手持设备上的纵向模式下时)在屏幕底部添加一个栏以显示应用栏(也称为操作栏)中的操作项)。 应用栏不是以少量操作项形式出现在屏幕顶部的应用栏中,而是分成了顶部导航区和底部操作项栏。 这可以确保操作项以及顶部的导航和标题元素都能获得合理的空间。 菜单项不会拆分到两个栏中,它们始终一起出现。 |
- android:windowSoftInputMode
Activity 的主窗口与包含屏幕软键盘的窗口的交互方式。 该属性的设置影响两个方面:
- 当 Activity 成为用户注意的焦点时软键盘的状态 — 隐藏还是可见。
- 对 Activity 主窗口所做的调整 — 是否将其尺寸调小以为软键盘腾出空间,或者当窗口部分被软键盘遮挡时是否平移其内容以使当前焦点可见。
该设置必须是下表所列的值之一,或者是一个“state...”值加上一个“adjust...”值的组合。 在任一组中设置多个值(例如,多个“state...”值)都会产生未定义结果。各值之间使用垂直条 (|) 分隔。 例如:
<activity android:windowSoftInputMode="stateVisible|adjustResize" . . . > |
此处设置的值(“stateUnspecified”和“adjustUnspecified”除外)替换主题中设置的值。
值 | 说明 |
"stateUnspecified" | 不指定软键盘的状态(隐藏还是可见)。 将由系统选择合适的状态,或依赖主题中的设置。 这是对软键盘行为的默认设置。 |
“stateUnchanged” | 当 Activity 转至前台时保留软键盘最后所处的任何状态,无论是可见还是隐藏。 |
“stateHidden” | 当用户选择 Activity 时 — 也就是说,当用户确实是向前导航到 Activity,而不是因离开另一 Activity 而返回时 — 隐藏软键盘。 |
“stateAlwaysHidden” | 当 Activity 的主窗口有输入焦点时始终隐藏软键盘。 |
“stateVisible” | 在正常的适宜情况下(当用户向前导航到 Activity 的主窗口时)显示软键盘。 |
“stateAlwaysVisible” | 当用户选择 Activity 时 — 也就是说,当用户确实是向前导航到 Activity,而不是因离开另一 Activity 而返回时 — 显示软键盘。 |
“adjustUnspecified” | 不指定 Activity 的主窗口是否调整尺寸以为软键盘腾出空间,或者窗口内容是否进行平移以在屏幕上显露当前焦点。 系统会根据窗口的内容是否存在任何可滚动其内容的布局视图来自动选择其中一种模式。 如果存在这样的视图,窗口将进行尺寸调整,前提是可通过滚动在较小区域内看到窗口的所有内容。 这是对主窗口行为的默认设置。 |
“adjustResize” | 始终调整 Activity 主窗口的尺寸来为屏幕上的软键盘腾出空间。 |
“adjustPan” | 不调整 Activity 主窗口的尺寸来为软键盘腾出空间, 而是自动平移窗口的内容,使当前焦点永远不被键盘遮盖,让用户始终都能看到其输入的内容。 这通常不如尺寸调正可取,因为用户可能需要关闭软键盘以到达被遮盖的窗口部分或与这些部分进行交互。 |
上述配置属性,如果不能全部理解也没有关系,后面讲解Activity的任务队、权限、进程以及窗口、主题、应用栏时还会详细讲解相关的属性具体用途。
(张伟:2018年10月17日)
(转载时请注明来源)