前言
在当前的这个互联网的时代中,对于程序员是越来越苛刻了 要求在不断的提高 ,尤其是android程序员 再也不是过去你能写写界面和网络接口就能找到很好的工作了,所以我们现在需要不到提升自己。
储备知识
我们先需要对任务又一个简单的认识,Android官网的解释是 任务是用户在执行某项工作时与之互动的一系列活动,他们是有顺序的排列在一个栈中,例如,电子邮件应用可能有一个活动来显示新邮件列表。当用户选择一封邮件时,系统会打开一个新的活动来显示该邮件。这个新的活动会添加到返回栈中。如果用户按返回按钮,这个新的Activity即会完成并从栈中退出。对于任务的我们旧先说到这
在Android中大多数的任务都是从设备的主屏幕上启动的,当用户轻触应用启动器中的图标时,改应用的任务就会转到前台运行,如果应用没有任务存在(应用最近没有使用过)可以创建一个新的任务,并且该应用的“主”Activity 将会作为堆栈的根 Activity 打开。
Activity的排列和处理 如下图所示
相信大家一看就明白这不就是栈这种数据结构吗?哈哈没错 就是
如果你一直按back返回键,返回栈中的Activity会逐个出栈,直到返回到主屏幕(或者是任务开始时运行的Activity),移除堆栈中的所有的Activity后 改任务将不复存在。让我们来思考一个问题 我们的Android手是不是会有很多很多的应用程序呢,在你在使用淘宝购物的时候在启动支付宝或者是微信支付之后你可以正确的返回到淘宝这个app正确的使用 这是怎么回事呢?其实我们的淘宝app是一个任务 我们的微信支付包又是另外的一个任务 ,他们这两个任务在一个栈里边管理这他们使用的所有的Activity,刚刚的那种情况就是任务的切换 。我们切换任务并不会破坏其内部的Activity的排列顺序等
Activity 和任务的默认行为总结如下:
- 当 Activity A 启动 Activity B 时,Activity A 会停止,但系统会保留其状态(例如滚动位置和输入到表单中的文本)。如果用户在 Activity B 中按返回按钮,系统会恢复 Activity A 及其状态。
- 当用户通过按主屏幕按钮离开任务时,当前 Activity 会停止,其任务会转到后台。系统会保留任务中每个 Activity 的状态。如果用户稍后通过点按该任务的启动器图标来恢复该任务,该任务会进入前台并恢复堆栈顶部的 Activity。
- 如果用户按返回按钮,当前 Activity 将从堆栈中退出并销毁。堆栈中的上一个 Activity 将恢复。Activity 被销毁后,系统不会保留该 Activity 的状态。
Activity 可以多次实例化,甚至是从其他任务对其进行实例化。
管理任务
Android 管理任务和返回堆栈的方式是将所有接连启动的 Activity 放到同一任务和一个“后进先出”堆栈中,这对于大多数应用都很有效,而且您不必担心 Activity 如何与任务相关联,或者它们如何存在于返回堆栈中。不过,您可能需要决定是否要打破正常行为。或许您希望应用中的某个 Activity 在启动时开启一个新的任务(而不是被放入当前的任务中),或者当您启动某个 Activity 时,您希望调用它的一个现有实例(而不是在返回堆栈顶部创建一个新实例),或者您希望在用户离开任务时清除返回堆栈中除根 Activity 以外的所有 Activity
你可以借助 清单配置文件中的属性以及传递给startActivity的intent中标记来实现上述目的。
- activity中的属性包括:
taskAffinity
launchMode
allowTaskReparenting
clearTaskOnLaunch
alwaysRetainTaskState
finishOnTaskLaunch
- intent标记包括
FLAG_ACTIVITY_NEW_TASK
FLAG_ACTIVITY_CLEAR_TOP
FLAG_ACTIVITY_SINGLE_TOP
定义启动模式
你可以通过启动模式定义Activity的新实例如何与当前的任务关联,可以通过如下方式设置启动模式
- 使用清单配置文件
当您在清单文件中声明 Activity 时,您可以指定该 Activity 在启动时如何与任务关联。具体使用如下
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Activitystudy">
<activity
android:launchMode="standard"
android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
-
启动模式详解
standard:(默认启动模式):
系统在启动该Activity的任务中创建Activity的新实例,并将intent传递给该实例,Activity可以多次实例化,每个实例可以属于不同的任务,一个任务可以拥有多个实例。singleTop:
如果当前任务的顶部已存在 Activity 的实例,则系统会通过调用其 onNewIntent() 方法来将 intent 转送给该实例,而不是创建 Activity 的新实例。Activity 可以多次实例化,每个实例可以属于不同的任务,一个任务可以拥有多个实例(但前提是返回堆栈顶部的 Activity 不是该 Activity 的现有实例)。
注意:创建 Activity 的新实例后,用户可以按返回按钮返回到上一个 Activity。但是,当由 Activity 的现有实例处理新 intent 时,用户将无法通过按返回按钮返回到 onNewIntent() 收到新 intent 之前的 Activity 状态。singleTask
系统会创建新任务,并实例化新任务的根 Activity。但是,如果另外的任务中已存在该 Activity 的实例,则系统会通过调用其 onNewIntent() 方法将 intent 转送到该现有实例,而不是创建新实例。Activity 一次只能有一个实例存在。singleInstance
与 “singleTask” 相似,唯一不同的是系统不会将任何其他 Activity 启动到包含该实例的任务中。该 Activity 始终是其任务唯一的成员;由该 Activity 启动的任何 Activity 都会在其他的任务中打开。
在举个例子:Android 浏览器应用在 元素中指定 singleTask 启动模式,由此声明网络浏览器 Activity 应始终在它自己的任务中打开。这意味着,如果您的应用发出打开 Android 浏览器的 intent,系统不会将其 Activity 置于您的应用所在的任务中,而是会为浏览器启动一个新任务,如果浏览器已经有任务在后台运行,则会将该任务转到前台来处理新 intent。
无论 Activity 是在新任务中启动的,还是在和启动它的 Activity 相同的任务中启动,用户按返回按钮都会回到上一个 Activity。但是,如果您启动了指定 singleTask 启动模式的 Activity,而后台任务中已存在该 Activity 的实例,则系统会将该后台任务整个转到前台运行。此时,返回堆栈包含了转到前台的任务中的所有 Activity,这些 Activity 都位于堆栈的顶部
-
使用Intent标记
当您调用 startActivity() 时,可以在 Intent 中添加一个标记,用于声明新 Activity 如何(或是否)与当前任务相关联。 -
启动模式详解
FLAG_ACTIVITY_NEW_TASK:对应于singleTask
FLAG_ACTIVITY_SINGLE_TOP:对应于singleTop
FLAG_ACTIVITY_CLEAR_TOP:如果要启动的 Activity 已经在当前任务中运行,则不会启动该 Activity 的新实例,而是会销毁位于它之上的所有其他 Activity,并通过 onNewIntent() 将此 intent 传送给它的已恢复实例(现在位于堆栈顶部)。
备注 :因此,如果 Activity A 启动 Activity B,Activity B 可在其清单中定义如何与当前任务相关联(如果关联的话),Activity A 也可以请求 Activity B 应该如何与当前任务关联。如果两个 Activity 都定义了 Activity B 应如何与任务关联,将优先遵循 Activity A 的请求(在 intent 中定义),而不是 Activity B 的请求(在清单中定义)。