本文的翻译是特别为从事Android开发的高级学生准备的。
活动是Android(最流行的移动操作系统,具有精心设计的内存管理架构,可以完美实现多任务)中最引人注目的概念之一。一种或另一种方式是,随着在屏幕上启动“活动”,并非一切都那么简单。它的运行方式也很重要。这个主题有很多细微差别。真正重要的功能之一是launchMode,我们将在本文中进行讨论。每个活动的创建都是为了实现不同的目标。其中一些被设计为与每个Intent分别工作,例如,为在邮件客户端中编写电子邮件而发送的活动。而另一些则设计为单例工作,例如活动邮箱。这就是为什么指出您是需要创建一个新的Activity还是使用一个现有的Activity如此重要的原因,否则会导致不良的UX或崩溃。感谢Android内核开发人员,使用为此专门设计的launchMode可以轻松做到这一点。LaunchMode定义
从本质上讲,我们可以定义launchMode直接作为标记属性<
activity>
中AndroidManifest.xml
:<activity
android:name=".SingleTaskActivity"
android:label="singleTask launchMode"
android:launchMode="singleTask">
有4种可用的launchMode。让我们一次看看他们。standard这是默认模式。设置为此模式的活动的行为将始终创建一个新的活动,以与每个发送的Intent分开工作。实际上,如果发送了10个意图来撰写电子邮件,则必须启动10个活动才能分别为每个意图提供服务。结果,可以在设备上启动无限数量的此类活动。棒棒糖Android之前的行为这种活动将在发送Intent的同一任务中创建并放置在堆栈的顶部。
下图显示了当我们与标准活动共享图像时会发生什么。尽管它们来自不同的应用程序,但是它将被堆叠在与上述相同的任务中。
这就是您将在任务管理器中看到的内容。 (这似乎有些奇怪)
如果我们将应用程序切换到另一个任务,然后再切换回Gallery,我们仍然会看到标准的launchMode放置在Gallery任务的顶部。因此,如果需要在图库中做某事,则必须首先在此附加活动中完成工作。Android Lollipop上的行为如果这些活动与同一应用程序相关,则其行为将与Lollipop之前的实现中的行为相同-放在任务顶部的堆栈中。
但是,如果Intent是从另一个应用程序发送的,则将创建一个新任务,并将新创建的Activity放置为根,如下所示。
这就是您将在任务管理器中看到的内容。
这是因为任务管理系统已在Lollipop中进行了修改-它变得更加完善和易于理解。在Lollipop中,您可以直接切换回Gallery,因为它是另一项任务。您可以发送另一个Intent,将创建一个新任务,该任务将以与上一个相同的方式服务于Intent。
这种活动的一个示例是撰写电子邮件活动或社交网络的状态发布活动。(社交网络上的状态更新)。如果您有一个单独处理每个Intent的Activity,那么您正在考虑标准Activity。单顶
下一个模式是singleTop。它的行为与standard几乎相同,这意味着您可以根据需要创建任意数量的singleTop Activity实例。唯一的区别是,如果在调用任务的堆栈顶部已经有一个具有相同类型的Activity实例,则不会创建新的Activity,而是将Intent通过该方法发送到现有的Activity实例onNewIntent()
。
在singleTop模式下,必须考虑在中处理传入的Intent onCreate()
,onNewIntent()
以便它在所有情况下均有效。搜索功能是使用此模式的一个示例。让我们考虑创建一个搜索框,该搜索框将您定向到SearchActivity以查看搜索结果。为了获得更好的用户体验,我们通常总是将搜索框放在搜索结果页面上,以允许用户执行下一个搜索而无需返回。现在想象一下,如果我们总是启动一个新的SearchActivity来提供一个新的搜索结果,那么对于10次搜索迭代,我们将获得10个新的Activity。返回是非常奇怪的,因为您必须单击10次以浏览所有搜索结果才能返回到根活动。相反,如果SearchActivity已经在堆栈的顶部,则最好将Intent发送到现有的Activity实例,并让其更新搜索结果。现在,堆栈顶部只有一个SearchActivity,您只需单击一次后退按钮即可返回上一个活动。这更有意义。在任何情况下,singleTop都与调用者在同一任务中工作。如果您希望将Intent发送到其他任何任务之上的现有Activity,那么我应该说它不再有效,这会让您感到失望。如果将Intent从其他应用程序发送到singleTop Activity,则新的Activity将以与标准artingMode(棒棒糖之前:放置在调用任务的顶部,棒棒糖:将创建一个新任务)。singleTask
此模式与standart和singleTop非常不同。具有singleTask launchMode的活动仅在系统中具有一个实例(ala singleton)。如果系统中已经存在一个Activity实例,则保存该实例的整个任务将上移,并且Intent将通过method提供onNewIntent()
。否则,将创建一个新的活动,并将其放置在相应的任务中。在一个应用程序中工作如果系统中没有singleTask Activity实例,则将创建一个新实例,并将其简单地放在同一任务的堆栈中。
但是,如果存在,位于该singleTask活动上方的所有活动将被自动残酷地销毁(生命周期已完成),以便在堆栈顶部显示所需的活动。同时,Intent将通过一种很棒的方法发送到singleTask活动onNewIntent()
。
从用户体验的角度来看,这没有任何意义,但是它是通过这种方式设计的。您会注意到文档中提到的一个细微差别:系统创建一个新任务,并在新任务的根目录处实例化一个活动实例。但是在实践中,这似乎不像所描述的那样起作用。从命令的结果可以看出,SingleTask Activity仍然位于任务的Activity堆栈的顶部dumpsys activity
。钽sk id #239
TaskRecord{428efe30 #239 A=com.thecheesefactory.lab.launchmode U=0 sz=2}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.thecheesefactory.lab.launchmode/.StandardActivity }
Hist #1: ActivityRecord{429a88d0 u0 com.thecheesefactory.lab.launchmode/.SingleTaskActivity t239}
Intent { cmp=com.thecheesefactory.lab.launchmode/.SingleTaskActivity }
ProcessRecord{42243130 18965:com.thecheesefactory.lab.launchmode/u0a123}
Hist #0: ActivityRecord{425fec98 u0 com.thecheesefactory.lab.launchmode/.StandardActivity t239}
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.thecheesefactory.lab.launchmode/.StandardActivity }
ProcessRecord{42243130 18965:com.thecheesefactory.lab.launchmode/u0a123}
如果您希望singleTask活动按照文档中的描述进行操作:创建一个新任务,并将Activity作为根活动。您需要taskAffinity
按以下方式为singleTask活动定义一个属性。<activity
android:name=".SingleTaskActivity"
android:label="singleTask launchMode"
android:launchMode="singleTask"
android:taskAffinity="">
这就是我们尝试运行时的结果SingleTaskActivity
。
您的任务是taskAffinity
根据活动的期望行为来决定是否使用。与另一个应用程序进行交互一旦从另一个应用程序发送了Intent,并且系统中没有创建Activity的实例,则将创建一个新任务,并将新的Activity放置为根Activity。
如果没有任务将成为调用singleTask活动的所有者,则会显示一个新的活动。
如果任务中存在一个Activity的实例,则整个任务将上移,对于位于单个Task Activity上方的每个Activity,生命周期将完成。。如果按下后退按钮,则用户必须先经过堆栈上的“活动”,然后才能返回到调用任务。
使用此模式的示例是任何入口点活动,例如,电子邮件客户端的收件箱页面或社交网络时间轴。这些活动不承担多个实例,因此singleTask将完美地完成其工作。在任何情况下,您都应该明智地使用此模式,因为在这种模式下,活动可能会被破坏而无需用户确认,如上所述。单实例
此模式与singleTask非常相似,在singleTask上,系统上只能存在一个Activity实例。区别在于,具有此Activity的任务只能具有一个Activity-一个具有singleInstance属性的任务。如果从此类活动中调用了另一个活动,则会自动创建一个新任务来适应该新活动。同样,如果调用singleInstance Activity,则将创建一个新任务来托管此Activity。无论如何,结果都是很奇怪的。从提供的信息dumpsys
,很明显,系统中有两个任务,但是任务管理器中只有一个任务出现,具体取决于哪个任务位于顶部。结果,尽管有任务仍在后台运行,但是我们无法将其切换回前台。这根本没有意义。这是在堆栈上已经存在活动时调用singleInstance活动的情况。
这就是我们在任务管理器中看到的内容。
由于此任务只能有一个活动,因此我们不能再切换回任务1。唯一的方法是从启动器重新启动应用程序,但是结果singleInstance任务将隐藏在后台。无论如何,有一些解决此问题的方法。与singleTask活动一样,只需将属性分配taskAffinity
给singleInstance活动,从而允许任务管理器中存在多个任务。<activity
android:name=".SingleInstanceActivity"
android:label="singleInstance launchMode"
android:launchMode="singleInstance"
android:taskAffinity="">
现在,图片变得更有意义了。
此模式很少使用。一些实际的用例是一个活动启动器或一个应用程序,您可以100%确保只有一个活动。无论如何,除非紧急情况,我建议您不要使用此模式。意图标志
除了AndroidManifest.xml
将启动模式直接设置为之外,我们还可以使用称为Intent标志的工具来调整行为,例如:Intent intent = new Intent(StandardActivity.this, StandardActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
将以StandardActivity
条件singleTop launchMode启动。您可以使用很多标志。您可以在此处找到有关此信息的更多信息。希望您觉得这篇文章对您有帮助=)了解有关该课程的更多信息