精华内容
下载资源
问答
  • Activity启动模式与任务栈(Task)全面深入记录(上)

    万次阅读 多人点赞 2016-07-30 11:37:47
    转载请注明出处(谢谢): http://blog.csdn.net/javazejian/article/details/52071885任务栈简单入门  最近又把两本进阶书看了一遍,但总...android任务栈简单了解1. android任务栈又称为Task,它是一个栈结构,具

    转载请注明出处(谢谢):
    http://blog.csdn.net/javazejian/article/details/52071885

    任务栈简单入门

      最近又把两本进阶书看了一遍,但总感觉好记性不如烂笔头,所以还是决定通过博客记录一下,我们将分两篇来全面深入地记录Activity 启动模式与任务栈的内容。

    android任务栈简单了解

    1. android任务栈又称为Task,它是一个栈结构,具有后进先出的特性,用于存放我们的Activity组件。
    2. 我们每次打开一个新的Activity或者退出当前Activity都会在一个称为任务栈的结构中添加或者减少一个Activity组件,因此一个任务栈包含了一个activity的集合, android系统可以通过Task有序地管理每个activity,并决定哪个Activity与用户进行交互:只有在任务栈栈顶的activity才可以跟用户进行交互。
    3. 在我们退出应用程序时,必须把所有的任务栈中所有的activity清除出栈时,任务栈才会被销毁。当然任务栈也可以移动到后台, 并且保留了每一个activity的状态. 可以有序的给用户列出它们的任务, 同时也不会丢失Activity的状态信息。
    4. 需要注意的是,一个App中可能不止一个任务栈,某些特殊情况下,单独一个Actvity可以独享一个任务栈。还有一点就是一个Task中的Actvity可以来自不同的App,同一个App的Activity也可能不在一个Task中。

      嗯,目前android任务栈的概念我们就大概了解到这。下面我们主要还是来聊聊android的4种启动模式。

    Activity的启动模式

    为什么需要Activity的启动模式?

      我们在开发项目的过程中,一般都需要在本应用中多个Activity组件之间的跳转,也可能需要在本应用中打开其它应用的可复用的Activity。如我们可能需要跳转到原来某个Activity实例,此时我们更希望这个Activity可以被重用而不是创建一个新的 Activity,但根据Android系统的默认行为,确实每次都会为我们创建一个新的Activity并添加到Task中,这样android系统是不是很傻?还有一点就是在我们每开启一次页面加入到任务栈Task中后,一个Activity的数据和信息状态都将会被保留,这样会造成数据冗余, 重复数据太多, 最终还可能导致内存溢出的问题(OOM)。为了解决这些问题,android系统提供了一套Activity的启动模式来修改系统Activity的默认启动行为。目前启动模式有四种,分别是standard,singleTop,singTask和singleInstance,接下来我们将分别介绍这四种模式。

    Activity的4种启动模式

    • Standard 模式

      又称为标准模式,也是系统的默认模式(可以不指定),在这样模式下,每启动一个Activity都会重新创建一个Activity的新实例,并且将其加入任务栈中,而且完全不会去考虑这个实例是否已存在。我们通过图解来更清晰地了解Standard模式:

      通过上图,我们可以发现,这个过程中,在standard模式下启动了三次MainActivity后,都生成了不同的新实例,并添加到同一个任务栈中。这个时候Activity的onCreate、onStart、onResume方法都会被调用。

    • singleTop 模式

      又称栈顶复用模式,顾名思义,在这种模式下,如果有新的Activity已经存在任务栈的栈顶,那么此Activity就不会被重新创建新实例,而是复用已存在任务栈栈顶的Activity。这里重点是位于栈顶,才会被复用,如果新的Activity的实例已存在但没有位于栈顶,那么新的Activity仍然会被重建。需要注意的是,Activity的onNewIntent方法会被调用,方法原型如下:

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
    }

      通过此方法的参数,我们可以获取当前请求的相关信息,此时Activity的onCreate、onStart方法不会被调用,因为Activity并没有被重建。同理,我们通过图解来协助我们更清晰的理解singleTop模式:

      从上图我们可以看出,当需要新创建的MainActivity位于栈顶时,MainActivity并没有重新创建。下面我们再来看看新创建的MainActivity没有位于栈顶的情况。

      嗯,这就是singTop模式。这种模式通常比较适用于接收到消息后显示的界面,如qq接收到消息后弹出Activity界面,如果一次来10条消息,总不能一次弹10个Activity,是吧?再比如新闻客户端收到了100个推送,你每次点一下推送他都会进入某个activiy界面(显示新闻只用一个activity,只是内容不同而已),这时也比较适合使用singleTop模式。

    • singleTask 模式

       又称为栈内复用模式。这是一种单例模式,与singTop点类似,只不过singTop是检测栈顶元素是否有需要启动的Activity,而singTask则是检测整个栈中是否存在当前需要启动的Activity,如果存在就直接将该Activity置于栈顶,并将该Activity以上的Activity都从任务栈中移出销毁,同时也会回调onNewIntent方法。情况如下图:

       从图中可以看出,当我们再次启动MainActivity时,由于MainActivity位于栈中,所以系统直接将其置于栈顶,并移除其上方的所有Activity。当然如果所需要的MainActivity不存在栈中,则会创建新的Activity并添加到栈中。singleTask 模式比较适合应用的主界面activity(频繁使用的主架构),可以用于主架构的activity,(如新闻,侧滑,应用主界面等)里面有好多fragment,一般不会被销毁,它可以跳转其它的activity 界面再回主架构界面,此时其他Activity就销毁了。当然singTask还有一些比较特殊的场景这个我们后面会一一通过情景代码分析。

    • singleInstance 模式

      在singleInstance模式下,该Activity在整个android系统内存中有且只有一个实例,而且该实例单独尊享一个Task。换句话说,A应用需要启动的MainActivity 是singleInstance模式,当A启动后,系统会为它创建一个新的任务栈,然后A单独在这个新的任务栈中,如果此时B应用也要激活MainActivity,由于栈内复用的特性,则不会重新创建,而是两个应用共享一个Activity的实例。如下图所示:

      从图中我们可以看到最终AB应用都共享一个singleInstance模式的MainActivity,也没有去重新创建。到此Activity的四种启动模式我们都介绍完了,下面我们接着来聊聊怎么使用启动模式。

    Activity启动模式的使用方式

      前面我们说了那么多,那么我们该如何给Activity指定启动模式呢?事实上共有如下两种方式:
    1.通过AndroidMenifest.xml文件为Activity指定启动模式,代码如下:

    <activity android:name=".ActivityC"android:launchMode="singleTask" />

    2.通过在Intent中设置标志位(addFlags方法)来为Activity指定启动模式,示例代码如下:

    Intent intent = new Intent();
    intent.setClass(ActivityB.this,ActivityA.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent);

    那么标志位是是什么呢?接下来我们就来了解一些常用的标志位

    Intent Flag 启动模式

      这里我们主要介绍一下一些常用的Activity的Flag,因为Activity的Flag比较多,我们知道一些常用的就够了,遇到比较特殊的还是查查官网文档吧。

    • Intent.FLAG_ACTIVITY_NEW_TASK

    该标志位表示使用一个新的Task来启动一个Activity,相当于在清单文件中给Activity指定“singleTask”启动模式。通常我们在Service启动Activity时,由于Service中并没有Activity任务栈,所以必须使用该Flag来创建一个新的Task。我们来重现一下这个错误,创建一个Service服务,并在onCreate方法中启动Activity,代码如下:

    public class ServiceT extends Service {
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            Intent i =new Intent(getApplicationContext(),ActivityD.class);
            startActivity(i);
        }
    }

    启动应用并启动Service服务,后报错如下:

    从异常信息我们可以看出,提示我们添加Intent.FLAG_ACTIVITY_NEW_TASK标志位,所以我们代码必须改成如下:

    public class ServiceT extends Service {
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
    
        @Override
        public void onCreate() {
            super.onCreate();
            Intent i =new Intent(getApplicationContext(),ActivityD.class);
            i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(i);
        }
    }
    • Intent.FLAG_ACTIVITY_SINGLE_TOP
        该标志位表示使用singleTop模式来启动一个Activity,与在清单文件指定android:launchMode="singleTop"效果相同。

    • Intent.FLAG_ACTIVITY_CLEAR_TOP
      
  该标志位表示使用singleTask模式来启动一个Activity,与在清单文件指定android:launchMode="singleTask"效果相同。

    • Intent.FLAG_ACTIVITY_NO_HISTORY
        使用该模式来启动Activity,当该Activity启动其他Activity后,该Activity就被销毁了,不会保留在任务栈中。如A-B,B中以这种模式启动C,C再启动D,则任务栈只有ABD。

    • Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
        使用该标识位启动的Activity不添加到最近应用列表,也即我们从最近应用里面查看不到我们启动的这个activity。与属性android:excludeFromRecents="true"效果相同。

    启动模式中singleTask的特殊情景

      前面我们在分析singleTask模式时,提到过singleTask模式有些比较特殊的场景,现在我们就来了解了解它们。
    特殊情景一:现在我们假设有如下两个Task栈,分别为前台任务栈和后台任务栈

      从图中我们看出前台任务栈分别为AB两个Activity,后台任务栈分别为CD两个任务栈,而且其启动模式均为singleTask,此时我们先启动CD,然后再启动AB,再有B启动D,此时后台任务栈便会被切换到前台,而且这个时候整个后退列表就变成了ABCD,请注意我们这里强调的是后退列表,而非栈合并。因此当用户点击back键时,列表中的Activity会依次按DCBA顺序出栈,如下图所示:

      这里我们通过两个应用ActivityTask和ActivityTask2来测试重现这个现象。因为两个是不同的应用所以启动时所在的栈也是不同。我们先启动ActivityTask2的应用,其ActivityC和ActivityD都是singleTask模式,然后再启动应用ActivityTask,此时ActivityC和ActivityD所在任务栈会被退居后台,而打开的ActivityA和ActivityB会在前台,而且都是默认模式。我们通过 adb shell dumpsys activity activities 命令查看此时栈的情况:

      我们可以看到由两个栈,分别为id=222且栈名为“com.cmcm.activitytask”的任务栈其包含ActivityA和ActivityB(下面简称AB,栈名一般默认和包名相同),另外一个任务栈,id=221,栈名为“com.cmcm.activitytask2”,其包含ActivityC和ActivityD(下面检测CD)。现在我们通过ActivityB去启动ActivityD,然后按back键回退。B调用D代码如下:

    import android.app.Activity;
    import android.content.ComponentName;
    import android.content.Intent;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    
    /**
     * Created by zejian
     * Time 16/7/23.
     * Description:
     */
    public class ActivityB extends Activity {
        private Button btn;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_b);
            btn= (Button) findViewById(R.id.main);
            btn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(Intent.ACTION_MAIN);
                    intent.addCategory(Intent.CATEGORY_LAUNCHER);
                    ComponentName cn = new ComponentName("com.cmcm.activitytask2", "com.cmcm.activitytask2.ActivityD");
                    intent.setComponent(cn);
                    startActivity(intent);
    
                }
            });
        }
    }

    运行结果如下:

      我们可以看到包含CD的任务栈被提前的,虽然CD隔开了,但是我们从id和栈名可以发现他们是同一个栈,而AB所在的栈则在CD所在栈的后面,所以此时我们按back回退时,退出顺序是这样的D->C->B->A,动态图如下:

      到这里我们就应该更加清晰的了解情景一的现象了。了解这点有什么用呢,这可以使用我们更好地去管理我们的任务栈,而不会导致栈混乱是进入一些用户本来就不需要界面,影响用户体验。

    特殊情景二:
      如果上面B不是请求启动D而是请求启动C,那么又会是什么情况呢?其实这个时候任务栈退出列表变成C->B->A,其实原因很简单,singleTask模式的ActivityC切换到栈顶时会导致在他之上的栈内的Activity出栈。同样我们还是使用上面的代码,把B启动D改为B启动C,那么此时B未启动C时任务栈的情况如下:

      我们仍然可以看到两个任务栈,分别为id=242,栈名“com.cmcm.activitytask”的Task,包含ActivityA和ActivityB;id=241,栈名“com.cmcm.activitytask2”的Task,包含ActivityC和ActivityD。此时我们通过B启动C后栈的情况变成如下情况

    因此,栈的退出列表就变成了C->B->A了,如下图所示:

    动态图如下:


      到此我们对SingleTask模式又有了更深入的理解,但是我们发现上面的例子使用的是两个应用,所以才会有不同的任务栈,那么我们能不能在一个应用中存在多个不同的任务栈呢(暂时不考虑singleInstance 模式)?答案当然是肯定的啦,这就需要通过taskAffinity属性来设置不同的任务栈名称,不过这点将放在下篇来记录,本篇就先到这里告一段落哈。

    展开全文
  • Android -- Activity之任务栈

    千次阅读 2017-07-29 18:24:41
    Android -- Activity之任务栈 PS:来源 - 任务栈 应用通常包含多个 Activity。每个 Activity 均应围绕用户可以执行的特定操作设计,并且能够启动其他 Activity。 例如,电子邮件应用可能有一个 Activity...

    Android -- Activity之任务栈


    PS:来源 - 任务栈


    应用通常包含多个 Activity。每个 Activity 均应围绕用户可以执行的特定操作设计,并且能够启动其他 Activity。 例如,电子邮件应用可能有一个 Activity 显示新邮件的列表。用户选择某邮件时,会打开一个新 Activity 以查看该邮件。

    一个 Activity 甚至可以启动设备上其他应用中存在的 Activity。例如,如果应用想要发送电子邮件,则可将 Intent 定义为执行“发送”操作并加入一些数据,如电子邮件地址和电子邮件。 然后,系统将打开其他应用中声明自己处理此类 Intent 的 Activity。在这种情况下,Intent 是要发送电子邮件,因此将启动电子邮件应用的“撰写”Activity(如果多个 Activity 支持相同 Intent,则系统会让用户选择要使用的 Activity)。发送电子邮件时,Activity 将恢复,看起来好像电子邮件 Activity 是您的应用的一部分。 即使这两个 Activity 可能来自不同的应用,但是 Android 仍会将 Activity 保留在相同的任务中,以维护这种无缝的用户体验。

    任务是指在执行特定作业时与用户交互的一系列 Activity。 这些 Activity 按照各自的打开顺序排列在堆栈(即返回栈)中。

    设备主屏幕是大多数任务的起点。当用户触摸应用启动器中的图标(或主屏幕上的快捷方式)时,该应用的任务将出现在前台。 如果应用不存在任务(应用最近未曾使用),则会创建一个新任务,并且该应用的“主”Activity 将作为堆栈中的根 Activity 打开。

    当前 Activity 启动另一个 Activity 时,该新 Activity 会被推送到堆栈顶部,成为焦点所在。 前一个 Activity 仍保留在堆栈中,但是处于停止状态。Activity 停止时,系统会保持其用户界面的当前状态。 用户按“返回”按钮时,当前 Activity 会从堆栈顶部弹出(Activity 被销毁),而前一个 Activity 恢复执行(恢复其 UI 的前一状态)。 堆栈中的 Activity 永远不会重新排列,仅推入和弹出堆栈:由当前 Activity 启动时推入堆栈;用户使用“返回”按钮退出时弹出堆栈。 因此,返回栈以“后进先出”对象结构运行。 图 1 通过时间线显示 Activity 之间的进度以及每个时间点的当前返回栈,直观呈现了这种行为。



    图 1. 显示任务中的每个新 Activity 如何向返回栈添加项目。 用户按“返回”按钮时,当前 Activity 随即被销毁,而前一个 Activity 恢复执行。


    如果用户继续按“返回”,堆栈中的相应 Activity 就会弹出,以显示前一个 Activity,直到用户返回主屏幕为止(或者,返回任务开始时正在运行的任意 Activity)。 当所有 Activity 均从堆栈中移除后,任务即不复存在。


    任务是一个有机整体,当用户开始新任务或通过“主页”按钮转到主屏幕时,可以移动到“后台”。 尽管在后台时,该任务中的所有 Activity 全部停止,但是任务的返回栈仍旧不变,也就是说,当另一个任务发生时,该任务仅仅失去焦点而已,如图 2 中所示。然后,任务可以返回到“前台”,用户就能够回到离开时的状态。 例如,假设当前任务(任务 A)的堆栈中有三个 Activity,即当前 Activity 下方还有两个 Activity。 用户先按“主页”按钮,然后从应用启动器启动新应用。 显示主屏幕时,任务 A 进入后台。新应用启动时,系统会使用自己的 Activity 堆栈为该应用启动一个任务(任务 B)。与该应用交互之后,用户再次返回主屏幕并选择最初启动任务 A 的应用。现在,任务 A 出现在前台,其堆栈中的所有三个 Activity 保持不变,而位于堆栈顶部的 Activity 则会恢复执行。 此时,用户还可以通过转到主屏幕并选择启动该任务的应用图标(或者,通过从概览屏幕选择该应用的任务)切换回任务 B。这是 Android 系统中的一个多任务示例。



    图 2. 两个任务:任务 B 在前台接收用户交互,而任务 A 则在后台等待恢复。


    注:后台可以同时运行多个任务。但是,如果用户同时运行多个后台任务,则系统可能会开始销毁后台 Activity,以回收内存资源,从而导致 Activity 状态丢失。


    由于返回栈中的 Activity 永远不会重新排列,因此如果应用允许用户从多个 Activity 中启动特定 Activity,则会创建该 Activity 的新实例并推入堆栈中(而不是将 Activity 的任一先前实例置于顶部)。 因此,应用中的一个 Activity 可能会多次实例化(即使 Activity 来自不同的任务),如图 3 所示。因此,如果用户使用“返回”按钮向后导航,则会按 Activity 每个实例的打开顺序显示这些实例(每个实例的 UI 状态各不相同)。 但是,如果您不希望 Activity 多次实例化,则可修改此行为。 具体操作方法将在后面的管理任务部分中讨论。



    图 3. 一个 Activity 将多次实例化。


    Activity 和任务的默认行为总结如下:

    • 当 Activity A 启动 Activity B 时,Activity A 将会停止,但系统会保留其状态(例如,滚动位置和已输入表单中的文本)。如果用户在处于 Activity B 时按“返回”按钮,则 Activity A 将恢复其状态,继续执行。
    • 用户通过按“主页”按钮离开任务时,当前 Activity 将停止且其任务会进入后台。 系统将保留任务中每个 Activity 的状态。如果用户稍后通过选择开始任务的启动器图标来恢复任务,则任务将出现在前台并恢复执行堆栈顶部的 Activity。
    • 如果用户按“返回”按钮,则当前 Activity 会从堆栈弹出并被销毁。 堆栈中的前一个 Activity 恢复执行。销毁 Activity 时,系统不会保留该 Activity 的状态。
    • 即使来自其他任务,Activity 也可以多次实例化。

    保存 Activity 状态


    正如上文所述,当 Activity 停止时,系统的默认行为会保留其状态。 这样一来,当用户导航回到上一个 Activity 时,其用户界面与用户离开时一样。 但是,在 Activity 被销毁且必须重建时,您可以而且应当主动使用回调方法保留 Activity 的状态。

    系统停止您的一个 Activity 时(例如,新 Activity 启动或任务转到前台),如果系统需要回收系统内存资源,则可能会完全销毁该 Activity。 发生这种情况时,有关该 Activity 状态的信息将会丢失。如果发生这种情况,系统仍会知道该 Activity 存在于返回栈中,但是当该 Activity 被置于堆栈顶部时,系统一定会重建 Activity(而不是恢复 Activity)。 为了避免用户的工作丢失,您应主动通过在 Activity 中实现 onSaveInstanceState() 回调方法来保留工作。

    管理任务


    Android 管理任务和返回栈的方式(如上所述,即:将所有连续启动的 Activity 放入同一任务和“后进先出”堆栈中)非常适用于大多数应用,而您不必担心 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

    在下文中,您将了解如何使用这些清单文件属性和 Intent 标志定义 Activity 与任务的关联方式,以及 Activity 在返回栈中的行为方式。

    此外,我们还单独介绍了有关如何在概览屏幕中显示和管理任务与 Activity 的注意事项。 如需了解详细信息,请参阅概览屏幕。 通常,您应该允许系统定义任务和 Activity 在概览屏幕中的显示方法,并且无需修改此行为。

    注意:大多数应用都不得中断 Activity 和任务的默认行为: 如果确定您的 Activity 必须修改默认行为,当使用“返回”按钮从其他 Activity 和任务导航回到该 Activity 时,请务必要谨慎并确保在启动期间测试该 Activity 的可用性。请确保测试导航行为是否有可能与用户的预期行为冲突。

    定义启动模式


    启动模式允许您定义 Activity 的新实例如何与当前任务关联。 您可以通过两种方法定义不同的启动模式:

    使用清单文件
    在清单文件中声明 Activity 时,您可以指定 Activity 在启动时应该如何与任务关联。
    使用 Intent 标志
    调用 startActivity() 时,可以在 Intent 中加入一个标志,用于声明新 Activity 如何(或是否)与当前任务关联。
    因此,如果 Activity A 启动 Activity B,则 Activity B 可以在其清单文件中定义它应该如何与当前任务关联(如果可能),并且 Activity A 还可以请求 Activity B 应该如何与当前任务关联。如果这两个 Activity 均定义 Activity B 应该如何与任务关联,则 Activity A 的请求(如 Intent 中所定义)优先级要高于 Activity B 的请求(如其清单文件中所定义)。

    注:某些适用于清单文件的启动模式不可用作 Intent 标志,同样,某些可用作 Intent 标志的启动模式无法在清单文件中定义。

    使用清单文件
    在清单文件中声明 Activity 时,您可以使用 <activity> 元素的 launchMode 属性指定 Activity 应该如何与任务关联。

    launchMode 属性指定有关应如何将 Activity 启动到任务中的指令。您可以分配给 launchMode 属性的启动模式共有四种:

    "standard"(默认模式)


    默认。系统在启动 Activity 的任务中创建 Activity 的新实例并向其传送 Intent。Activity 可以多次实例化,而每个实例均可属于不同的任务,并且一个任务可以拥有多个实例。


    "singleTop"


    如果当前任务的顶部已存在 Activity 的一个实例,则系统会通过调用该实例的 onNewIntent() 方法向其传送 Intent,而不是创建 Activity 的新实例。Activity 可以多次实例化,而每个实例均可属于不同的任务,并且一个任务可以拥有多个实例(但前提是位于返回栈顶部的 Activity 并不是 Activity 的现有实例)。
    例如,假设任务的返回栈包含根 Activity A 以及 Activity B、C 和位于顶部的 D(堆栈是 A-B-C-D;D 位于顶部)。收到针对 D 类 Activity 的 Intent。如果 D 具有默认的 "standard" 启动模式,则会启动该类的新实例,且堆栈会变成 A-B-C-D-D。但是,如果 D 的启动模式是 "singleTop",则 D 的现有实例会通过 onNewIntent() 接收 Intent,因为它位于堆栈的顶部;而堆栈仍为 A-B-C-D。但是,如果收到针对 B 类 Activity 的 Intent,则会向堆栈添加 B 的新实例,即便其启动模式为 "singleTop" 也是如此。

    注:为某个 Activity 创建新实例时,用户可以按“返回”按钮返回到前一个 Activity。 但是,当 Activity 的现有实例处理新 Intent 时,则在新 Intent 到达 onNewIntent() 之前,用户无法按“返回”按钮返回到 Activity 的状态。

    "singleTask"


    系统创建新任务并实例化位于新任务底部的 Activity。但是,如果该 Activity 的一个实例已存在于一个单独的任务中,则系统会通过调用现有实例的 onNewIntent() 方法向其传送 Intent,而不是创建新实例。一次只能存在 Activity 的一个实例。
    注:尽管 Activity 在新任务中启动,但是用户按“返回”按钮仍会返回到前一个 Activity。

    "singleInstance"


    与 "singleTask" 相同,只是系统不会将任何其他 Activity 启动到包含实例的任务中。该 Activity 始终是其任务唯一仅有的成员;由此 Activity 启动的任何 Activity 均在单独的任务中打开。


    我们再来看另一示例,Android 浏览器应用声明网络浏览器 Activity 应始终在其自己的任务中打开(通过在 <activity> 元素中指定 singleTask 启动模式)。这意味着,如果您的应用发出打开 Android 浏览器的 Intent,则其 Activity 与您的应用位于不同的任务中。相反,系统会为浏览器启动新任务,或者如果浏览器已有任务正在后台运行,则会将该任务上移一层以处理新 Intent。

    无论 Activity 是在新任务中启动,还是在与启动 Activity 相同的任务中启动,用户按“返回”按钮始终会转到前一个 Activity。 但是,如果启动指定 singleTask 启动模式的 Activity,则当某后台任务中存在该 Activity 的实例时,整个任务都会转移到前台。此时,返回栈包括上移到堆栈顶部的任务中的所有 Activity。 图 4 显示了这种情况。



    图 4. 显示如何将启动模式为“singleTask”的 Activity 添加到返回栈。 如果 Activity 已经是某个拥有自己的返回栈的后台任务的一部分,则整个返回栈也会上移到当前任务的顶部。


    注:使用 launchMode 属性为 Activity 指定的行为可由 Intent 附带的 Activity 启动标志替代,下文将对此进行讨论。

    使用 Intent 标志
    启动 Activity 时,您可以通过在传递给 startActivity() 的 Intent 中加入相应的标志,修改 Activity 与其任务的默认关联方式。可用于修改默认行为的标志包括:

    FLAG_ACTIVITY_NEW_TASK


    在新任务中启动 Activity。如果已为正在启动的 Activity 运行任务,则该任务会转到前台并恢复其最后状态,同时 Activity 会在 onNewIntent() 中收到新 Intent。
    正如前文所述,这会产生与 "singleTask"launchMode 值相同的行为。

    FLAG_ACTIVITY_SINGLE_TOP


    如果正在启动的 Activity 是当前 Activity(位于返回栈的顶部),则 现有实例会接收对 onNewIntent() 的调用,而不是创建 Activity 的新实例。
    正如前文所述,这会产生与 "singleTop"launchMode 值相同的行为。

    FLAG_ACTIVITY_CLEAR_TOP


    如果正在启动的 Activity 已在当前任务中运行,则会销毁当前任务顶部的所有 Activity,并通过 onNewIntent() 将此 Intent 传递给 Activity 已恢复的实例(现在位于顶部),而不是启动该 Activity 的新实例。


    产生这种行为的 launchMode 属性没有值。

    FLAG_ACTIVITY_CLEAR_TOP 通常与 FLAG_ACTIVITY_NEW_TASK 结合使用。一起使用时,通过这些标志,可以找到其他任务中的现有 Activity,并将其放入可从中响应 Intent 的位置。

    注:如果指定 Activity 的启动模式为 "standard",则该 Activity 也会从堆栈中移除,并在其位置启动一个新实例,以便处理传入的 Intent。 这是因为当启动模式为 "standard" 时,将始终为新 Intent 创建新实例。

    处理关联


    关联”指示 Activity 优先属于哪个任务。默认情况下,同一应用中的所有 Activity 彼此关联。 因此,默认情况下,同一应用中的所有 Activity 优先位于相同任务中。 不过,您可以修改 Activity 的默认关联。 在不同应用中定义的 Activity 可以共享关联,或者可为在同一应用中定义的 Activity 分配不同的任务关联。

    可以使用 <activity> 元素的 taskAffinity 属性修改任何给定 Activity 的关联。

    taskAffinity 属性取字符串值,该值必须不同于在 <manifest> 元素中声明的默认软件包名称,因为系统使用该名称标识应用的默认任务关联。

    在两种情况下,关联会起作用:

    • 启动 Activity 的 Intent 包含 FLAG_ACTIVITY_NEW_TASK 标志。
      默认情况下,新 Activity 会启动到调用 startActivity() 的 Activity 任务中。它将推入与调用方相同的返回栈。 但是,如果传递给 startActivity() 的 Intent 包含 FLAG_ACTIVITY_NEW_TASK 标志,则系统会寻找其他任务来储存新 Activity。这通常是新任务,但未做强制要求。 如果现有任务与新 Activity 具有相同关联,则会将 Activity 启动到该任务中。 否则,将开始新任务。
      如果此标志导致 Activity 开始新任务,且用户按“主页”按钮离开,则必须为用户提供导航回任务的方式。 有些实体(如通知管理器)始终在外部任务中启动 Activity,而从不作为其自身的一部分启动 Activity,因此它们始终将 FLAG_ACTIVITY_NEW_TASK 放入传递给 startActivity() 的 Intent 中。请注意,如果 Activity 能够由可以使用此标志的外部实体调用,则用户可以通过独立方式返回到启动的任务,例如,使用启动器图标(任务的根 Activity 具有 CATEGORY_LAUNCHER Intent 过滤器;请参阅下面的启动任务部分)。
    • Activity 将其 allowTaskReparenting 属性设置为 "true"。
      在这种情况下,Activity 可以从其启动的任务移动到与其具有关联的任务(如果该任务出现在前台)。
      例如,假设将报告所选城市天气状况的 Activity 定义为旅行应用的一部分。 它与同一应用中的其他 Activity 具有相同的关联(默认应用关联),并允许利用此属性重定父级。当您的一个 Activity 启动天气预报 Activity 时,它最初所属的任务与您的 Activity 相同。 但是,当旅行应用的任务出现在前台时,系统会将天气预报 Activity 重新分配给该任务并显示在其中。
    提示:如果从用户的角度来看,一个 .apk 文件包含多个“应用”,则您可能需要使用 taskAffinity 属性将不同关联分配给与每个“应用”相关的 Activity。

    清理返回栈


    如果用户长时间离开任务,则系统会清除所有 Activity 的任务,根 Activity 除外。 当用户再次返回到任务时,仅恢复根 Activity。系统这样做的原因是,经过很长一段时间后,用户可能已经放弃之前执行的操作,返回到任务是要开始执行新的操作。

    您可以使用下列几个 Activity 属性修改此行为:

    alwaysRetainTaskState
    如果在任务的根 Activity 中将此属性设置为 "true",则不会发生刚才所述的默认行为。即使在很长一段时间后,任务仍将所有 Activity 保留在其堆栈中。


    clearTaskOnLaunch
    如果在任务的根 Activity 中将此属性设置为 "true",则每当用户离开任务然后返回时,系统都会将堆栈清除到只剩下根 Activity。 换而言之,它与 alwaysRetainTaskState 正好相反。 即使只离开任务片刻时间,用户也始终会返回到任务的初始状态。


    finishOnTaskLaunch
    此属性类似于 clearTaskOnLaunch,但它对单个 Activity 起作用,而非整个任务。 此外,它还有可能会导致任何 Activity 停止,包括根 Activity。 设置为 "true" 时,Activity 仍是任务的一部分,但是仅限于当前会话。如果用户离开然后返回任务,则任务将不复存在。


    启动任务


    通过为 Activity 提供一个以 "android.intent.action.MAIN" 为指定操作、以 "android.intent.category.LAUNCHER" 为指定类别的 Intent 过滤器,您可以将 Activity 设置为任务的入口点。 例如:

    <activity ... >
        <intent-filter ... >
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        ...
    </activity>
    此类 Intent 过滤器会使 Activity 的图标和标签显示在应用启动器中,让用户能够启动 Activity 并在启动之后随时返回到创建的任务中。

    第二个功能非常重要:用户必须能够在离开任务后,再使用此 Activity 启动器返回该任务。 因此,只有在 Activity 具有 ACTION_MAIN 和 CATEGORY_LAUNCHER 过滤器时,才应该使用将 Activity 标记为“始终启动任务”的两种启动模式,即 "singleTask" 和 "singleInstance"。例如,我们可以想像一下如果缺少过滤器会发生什么情况: Intent 启动一个 "singleTask" Activity,从而启动一个新任务,并且用户花了些时间处理该任务。然后,用户按“主页”按钮。 任务现已发送到后台,而且不可见。现在,用户无法返回到任务,因为该任务未显示在应用启动器中。

    如果您并不想用户能够返回到 Activity,对于这些情况,请将 <activity> 元素的 finishOnTaskLaunch 设置为 "true"




    展开全文
  • 彻底弄懂Activity的启动模式和任务栈

    千次阅读 2018-03-03 00:02:21
    Activity的启动模式和任务栈是Android的重点和难点,也是Android面试的常考必考知识点,而很多同学即使时搞Android开发好几年的同学也不一定完全搞懂了,可能也是一知半解。本文让你彻底搞懂Android中Activity的启动...

    Activity的启动模式和任务栈是Android的重点和难点,也是Android面试的常考必考知识点,而很多同学即使时搞Android开发好几年的同学也不一定完全搞懂了,可能也是一知半解。本文让你彻底搞懂Android中Activity的启动模式和任务栈!

    前言

    一个应用程序当中通常都会包含很多个Activity,每个Activity都是一个具有特定的功能,并且可以让用户进行操作的组件。另外,Activity之间可以相互启动,当前应用的Activity甚至可以去启动其他应用的Activity。

    比如你的应用希望去发送一封邮件,你就可以定义一个具有”send”动作的Intent,并且传入一些数据,如对方邮箱地址、邮件内容等。这样,如果另外一个应用程序中的某个Activity声明自己是可以响应这种Intent的,那么这个Activity就会被打开。当邮件发送之后,按下返回键仍然还是会回到你的应用程序当中,这让用户看起来好像刚才那个编写邮件的Activity就是你的应用程序当中的一部分。

    所以说,即使有很多个Activity分别都是来自于不同应用程序的,Android系统仍然可以将它们无缝地结合到一起。

    那这一切是怎么实现的呢?这就要讲到本文要介绍的Activity任务栈以及Activity启动模式了。

    任务栈是什么

    任务栈Task,是一种用来放置Activity实例的容器,他是以栈的形式进行盛放,也就是所谓的先进后出,主要有2个基本操作:压栈和出栈,其所存放的Activity是不支持重新排序的,只能根据压栈和出栈操作更改Activity的顺序。

    启动一个Application的时候,系统会为它默认创建一个对应的Task,用来放置根Activity。默认启动Activity会放在同一个Task中,新启动的Activity会被压入启动它的那个Activity的栈中,并且显示它。当用户按下回退键时,这个Activity就会被弹出栈,按下Home键回到桌面,再启动另一个应用,这时候之前那个Task就被移到后台,成为后台任务栈,而刚启动的那个Task就被调到前台,成为前台任务栈,Android系统显示的就是前台任务栈中的Top实例Activity。

    任务栈的作用

    以往基于应用(application)的程序开发中,程序具有明确的边界,一个程序就是一个应用,一个应用为了实现功能可以采用开辟新线程甚至新进程来辅助,但是应用与应用之间不能复用资源和功能。

    而Android引入了基于组件开发的软件架构,虽然我们开发android程序,仍然使用一个apk工程一个Application的开发形式,但是对于Aplication的开发就用到了Activity、service等四大组件,其中的每一个组件,都是可以被跨应用复用的,这就是android的神奇之处。

    虽然组件可以跨应用被调用,但是一个组件所在的进程必须是在组件所在的Aplication进程中。由于android强化了组件概念,弱化了Aplication的概念,所以在android程序开发中,A应用的A组件想要使用拍照或录像的功能就可以不用去针对Camera类进行开发,直接调用系统自带的摄像头应用(称其B应用)中的组件(称其B组件)就可以了,

    但是这就引发了一个新问题,A组件运行在A应用中,B组件运行在B应用中,自然都不在同一个进程中,那么从B组件中返回的时候,如何实现正确返回到A组件呢?Task就是来负责实现这个功能的,它是从用户角度来理解应用而建立的一个抽象概念。因为用户所能看到的组件就是Activity,所以Task可以理解为实现一个功能而负责管理所有用到的Activity实例的栈。

    栈是一个先进后出的线性表,根据Activity在当前栈结构中的位置,来决定该Activity的状态。正常情况下,当一个Activity启动了另一个Activity的时候,新启动的Activity就会置于任务栈的顶端,并处于活动状态,而启动它的Activity虽然成功身退,但依然保留在任务栈中,处于停止状态,当用户按下返回键或者调用finish()方法时,系统会移除顶部Activity,让后面的Activity恢复活动状态。当然,世界不可能一直这么“和谐”,可以给Activity设置一些“特权”,来打破这种“和谐”的模式,这种特权,就是通过在AndroidManifest文件中的属性andorid:launchMode来设置或者通过Intent的flag来设置的,下面就先介绍下Activity的几种启动模式。

    standard

    默认模式,可以不用写配置。在这个模式下,都会默认创建一个新的实例。因此,在这种模式下,可以有多个相同的实例,也允许多个相同Activity叠加。应用场景:绝大多数Activity。


    如果以这种方式启动的Activity被跨进程调用,在5.0之前新启动的Activity实例会放入发送Intent的Task的栈的顶部,尽管它们属于不同的程序,这似乎有点费解看起来也不是那么合理,所以在5.0之后,上述情景会创建一个新的Task,新启动的Activity就会放入刚创建的Task中,这样就合理的多了。

    singleTop

    栈顶复用模式,如果要开启的activity在任务栈的顶部已经存在,就不会创建新的实例,而是调用 onNewIntent() 方法。避免栈顶的activity被重复的创建。应用场景:在通知栏点击收到的通知,然后需要启动一个Activity,这个Activity就可以用singleTop,否则每次点击都会新建一个Activity。当然实际的开发过程中,测试妹纸没准给你提过这样的bug:某个场景下连续快速点击,启动了两个Activity。如果这个时候待启动的Activity使用 singleTop模式也是可以避免这个Bug的。

    同standard模式,如果是外部程序启动singleTop的Activity,在Android 5.0之前新创建的Activity会位于调用者的Task中,5.0及以后会放入新的Task中。

    singleTask

    栈内复用模式, activity只会在任务栈里面存在一个实例。如果要激活的activity,在任务栈里面已经存在,就不会创建新的activity,而是复用这个已经存在的activity,调用 onNewIntent() 方法,并且清空这个activity任务栈上面所有的activity。应用场景:大多数App的主页。对于大部分应用,当我们在主界面点击回退按钮的时候都是退出应用,那么当我们第一次进入主界面之后,主界面位于栈底,以后不管我们打开了多少个Activity,只要我们再次回到主界面,都应该使用将主界面Activity上所有的Activity移除的方式来让主界面Activity处于栈顶,而不是往栈顶新加一个主界面Activity的实例,通过这种方式能够保证退出应用时所有的Activity都能报销毁。

    在跨应用Intent传递时,如果系统中不存在singleTask Activity的实例,那么将创建一个新的Task,然后创建SingleTask Activity的实例,将其放入新的Task中。

    1. 假如目前有个任务栈T1中的情况是ABC,这个时候ActivityD以singleTask模式请求启动,其所需要的任务栈正是T1,则系统会直接创建D的实例并将其入栈到T1中。

    2. 假如DActivity启动所需要的任务栈为T2,由于T2和D的实例均不存在,那么系统会先创建任务栈T2,然后再创建D的实例并将其入栈到T2中。我们可以通过设置Activity的taskAffinity属性来模拟这一场景。

    <activity android:name=".SingleTastActivtiy" android:label="singleTask launchmode" android:launchMode="signleTask" android:taskAffinity="">

    1. 如果D所需的任务栈为T3,并且当前任务栈T3的情况为ADBC,根据栈内复用的原则,此时D不会重新创建,系统会把D切换到栈顶并调用其onNewIntent()方法,同时由于singleTask默认具有ClearTop的效果,会导致栈内所有在D上面的Activity全部出栈,于是最终T3的情况为AD。

    2. 假如目前有两个任务栈,前台任务栈T4的情况为AB,后台任务栈t4里存有CD,假设CD的启动模式均为singleTask,现在由B去启动D,那么整个后台任务都会被切换到前台,这个时候整个栈就变成了ABCD。

    1. 假如上面的其他条件不变,B启动的是C而不是D,那么整个栈的情况就变成了ABC,因为D在C上面,会被清理出栈。

    singleInstance

    单一实例模式,整个手机操作系统里面只有一个实例存在。不同的应用去打开这个activity 共享公用的同一个activity。他会运行在自己单独,独立的任务栈里面,并且任务栈里面只有他一个实例存在。应用场景:呼叫来电界面。这种模式的使用情况比较罕见,在Launcher中可能使用。或者你确定你需要使Activity只有一个实例。建议谨慎使用。

    设置Intent的Flag

    系统提供了两种方式来设置一个Activity的启动模式,除了在AndroidManifest文件中设置以外,还可以通过Intent的Flag来设置一个Activity的启动模式,下面我们在简单介绍下一些Flag。

    FLAG_ACTIVITY_NEW_TASK

    使用一个新的Task来启动一个Activity,但启动的每个Activity都讲在一个新的Task中。该Flag通常使用在从Service中启动Activity的场景,由于Service中并不存在Activity栈,所以使用该Flag来创建一个新的Activity栈,并创建新的Activity实例。

    FLAG_ACTIVITY_SINGLE_TOP

    使用singletop模式启动一个Activity,与指定android:launchMode=“singleTop”效果相同。

    FLAG_ACTIVITY_CLEAR_TOP

    使用SingleTask模式来启动一个Activity,与指定android:launchMode=“singleTask”效果相同。

    FLAG_ACTIVITY_NO_HISTORY

    Activity使用这种模式启动Activity,当该Activity启动其他Activity后,该Activity就消失了,不会保留在Activity栈中。

    LaunchMode与StartActivityForResult

    我们在开发过程中经常会用到StartActivityForResult方法启动一个Activity,然后在onActivityResult()方法中可以接收到上个页面的回传值,但你有可能遇到过拿不到返回值的情况,那有可能是因为Activity的LaunchMode设置为了singleTask。5.0之后,android的LaunchMode与StartActivityForResult的关系发生了一些改变。两个Activity,A和B,现在由A页面跳转到B页面,看一下LaunchMode与StartActivityForResult之间的关系:


    这是为什么呢?

    这是因为ActivityStackSupervisor类中的startActivityUncheckedLocked方法在5.0中进行了修改。在5.0之前,当启动一个Activity时,系统将首先检查Activity的launchMode,如果为A页面设置为SingleInstance或者B页面设置为singleTask或者singleInstance,则会在LaunchFlags中加入FLAG_ACTIVITY_NEW_TASK标志,而如果含有FLAG_ACTIVITY_NEW_TASK标志的话,onActivityResult将会立即接收到一个cancle的信息,而5.0之后这个方法做了修改,修改之后即便启动的页面设置launchMode为singleTask或singleInstance,onActivityResult依旧可以正常工作,也就是说无论设置哪种启动方式,StartActivityForResult和onActivityResult()这一组合都是有效的。所以如果你目前正好基于5.0做相关开发,不要忘了向下兼容,这里有个坑请注意避让。

    总结

    实际开发过程中如果采用比较合理的Activity启动模式来做好任务栈的管理,可以事半功倍。在launchMode的选择上首先要搞清楚当前的Activity的作用,以及实际使用场景来做出合理选择。

    展开全文
  • 任务栈简单入门

    千次阅读 2018-06-27 09:33:56
    最近又把两本进阶书看了一遍,但总感觉好记性不如烂笔头,所以还是决定通过博客记录一下,我们将分两篇来全面深入地记录Activity 启动模式与任务栈的内容。android任务栈简单了解1. android任务栈又称为Task,它是一...

       最近又把两本进阶书看了一遍,但总感觉好记性不如烂笔头,所以还是决定通过博客记录一下,我们将分两篇来全面深入地记录Activity 启动模式与任务栈的内容。

    android任务栈简单了解

    1. android任务栈又称为Task,它是一个栈结构,具有后进先出的特性,用于存放我们的Activity组件。
    2. 我们每次打开一个新的Activity或者退出当前Activity都会在一个称为任务栈的结构中添加或者减少一个Activity组件,因此一个任务栈包含了一个activity的集合, android系统可以通过Task有序地管理每个activity,并决定哪个Activity与用户进行交互:只有在任务栈栈顶的activity才可以跟用户进行交互。
    3. 在我们退出应用程序时,必须把所有的任务栈中所有的activity清除出栈时,任务栈才会被销毁。当然任务栈也可以移动到后台, 并且保留了每一个activity的状态. 可以有序的给用户列出它们的任务, 同时也不会丢失Activity的状态信息。
    4. 需要注意的是,一个App中可能不止一个任务栈,某些特殊情况下,单独一个Actvity可以独享一个任务栈。还有一点就是一个Task中的Actvity可以来自不同的App,同一个App的Activity也可能不在一个Task中。

      嗯,目前android任务栈的概念我们就大概了解到这。下面我们主要还是来聊聊android的4种启动模式。

    Activity的启动模式

    为什么需要Activity的启动模式?

      我们在开发项目的过程中,一般都需要在本应用中多个Activity组件之间的跳转,也可能需要在本应用中打开其它应用的可复用的Activity。如我们可能需要跳转到原来某个Activity实例,此时我们更希望这个Activity可以被重用而不是创建一个新的 Activity,但根据Android系统的默认行为,确实每次都会为我们创建一个新的Activity并添加到Task中,这样android系统是不是很傻?还有一点就是在我们每开启一次页面加入到任务栈Task中后,一个Activity的数据和信息状态都将会被保留,这样会造成数据冗余, 重复数据太多, 最终还可能导致内存溢出的问题(OOM)。为了解决这些问题,android系统提供了一套Activity的启动模式来修改系统Activity的默认启动行为。目前启动模式有四种,分别是standard,singleTop,singTask和singleInstance,接下来我们将分别介绍这四种模式。

    展开全文
  • Android任务栈的完全解析

    千次阅读 2016-07-19 15:26:31
    手机的Home界面是大多数任务开始的地方, 转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/41087993 本篇文章主要内容来自于Android Doc,我翻译之后又做了些加工,英文好的朋友也可以直接去...
  • 一上来就直接说给我开发一个什么软件,不说具体需求,没有需求文档的都不靠谱,这样的项目...国内远程工作平台,接单平台 1、任务栈 官方网站:http://www.renwuzhan.top/task 互联网软件外包服务平台,平台以外包为主
  • 三、 singleTask 栈内复用模式 任务栈处理 ( 前台任务栈 | 后台任务栈 )、 四、 singleTask 模式 存在 Activity 实例的任务栈处理、 五、 FLAG_ACTIVITY_BROUGHT_TO_FRONT 常量解析、 六、 singleTask 栈内复用...
  • Java基础知识面试题(2020最新版)

    万次阅读 多人点赞 2020-02-19 12:11:27
    为了使计算机能够理解人的意图,人类就必须要将需解决的问题的思路、方法、和手段通过计算机能够理解的形式告诉计算机,使得计算机能够根据人的指令一步一步去工作,完成某种特定的任务。这种人和计算机之间交流的...
  • 2018年快来了,BAT等一二线互联网公司Android面试题汇总作者:尹star博客:https://www.jianshu.com/p/2a9fcf3c11e4Activity的启动模式和任务栈是Android的重点和难点,也是Android面试的常考必考知识点,而很多同学...
  • Activity 启动模式及任务栈管理

    万次阅读 2016-07-24 21:04:08
    android任务栈描述,简述四种启动模式包括standard、singleTop、singleTask、singleInstance,并用实例说明他们之间的区别。
  • Android官方说明-Activity任务栈

    千次阅读 2016-05-30 23:35:48
    任务和返回 本文内容 保存 Activity 状态管理任务 定义启动模式处理关联清理返回启动任务 文章 Android 多任务运行机制 另请参阅 Android 设计:导航 清单文件元素概览...
  • 15 个优秀开源的 Spring Boot 学习项目,一网打尽!

    万次阅读 多人点赞 2019-12-12 11:44:43
    Spring Boot 算是目前 Java 领域最火的技术了,松哥年初出版的 《Spring Boot + Vue 全栈开发实战》迄今为止已经加印了 8 次,Spring Boot 的受欢迎程度可见一斑。经常有人问松哥有没有推荐的 Spring Boot 学习...
  • Android 任务栈

    2014-11-29 22:25:46
    在android中,一个activity组件可以激活另一个activity组件(可能属于另一个应用程序)。 ...Android是通过将之前的activity组件和新被激活的activity组件放入同一个任务栈来实现这个功能的。从用
  • 然后用户又重新打开了第一次使用的程序,这个时候任务A又会回到前台,A任务栈中的三个Activity仍然会保留着刚才的顺序,最顶端的Activity将重新变为运行状态。之后用户仍然可以通过Home键或者多任务键来切换回任务B...
  • Android Activity任务和返回全面解析

    千次阅读 2016-10-17 21:03:14
    任务和返回一个应用程序当中通常都会包含很多个Activity,每个Activity都应该设计成为一个具有特定的功能,并且可以让用户进行操作的组件。另外,Activity之间还应该是可以相互启动的。比如,一个邮件应用中可能会...
  • 任务栈和返回堆栈

    千次阅读 2012-11-21 15:23:53
    如果该应用在任务栈中不存在(应用在近段时间内没有使用过)就会在任务栈中创建一个新的任务,并将该应用作为"主"Activity放置在根任务栈中. 当前Activity开始时,新的Activity推入堆栈的顶部和焦点.以前的...
  • 最近再做一个功能,需求是: 当用户账号在异地登录,不管用户在哪个页面,都要去打开登录界面,...把MainActivity页面在单独的任务栈中放置,代码如下: 在配置清单文件中: <activity android:name=".Activity.MainActivit
  • 第二周:开始软件开发(构建项目) 下来,让我们朝着软件开发任务进军吧!不妨尝试综合你学到的知识完成一个实际的项目: 第一天:熟悉一种 IDE(5 小时): IDE 是你在编写大型项目时的操作环境,所以你需要精通...
  • 1、首先,由于Javascript是线程这个本质才会有下来的一系列下文。 2、堆、、队列: 堆:堆是在程序运行时,而不是在程序编译时,动态申请某个大小的内存空间,即动态分配内存。 :简言之:‘使用堆的一...
  • 计算机网络谢希仁第七版 课后答案

    万次阅读 多人点赞 2019-09-03 23:13:25
    协议:指计算机网络体系结构采用分层模型后,每层的主要功能由对等层协议的运行来实现,因而每层可用一些主要协议来表征,几个层次画在一起很像一个的结构.对等层:在网络体系结构中,通信双方实现同样功能的层. 协议...
  • 第二周:开始软件开发(构建项目) 下来,让我们朝着软件开发任务进军吧!不妨尝试综合你学到的知识完成一个实际的项目: 第一天:熟悉一种 IDE(5 小时): IDE 是你在编写大型项目时的操作环境,所以你需要精通...
  •  Android 管理任务和返回的方式(如上所述,即:将所有连续启动的 Activity 放入同一任务和“后进先出”堆栈中)非常适用于大多数应用,而您不必担心 Activity 如何与任务关联或者如何存在于返回中。...
  • Activity任务栈和启动模式

    千次阅读 2011-09-22 16:04:01
     若一个activity组件的allowTaskReparenting被置为“true”,则当与这个activity有相同的亲属关系的任务栈被切换到前台的时候,这个activity会从当前存在的任务栈中移动到与其有相同的亲属关系的任务栈中。...
  • 38、如果你的助手想要打印出当前的目录,你会建议他怎么做? 39、你的系统目前有许多正在运行的任务,在不重启机器的条件下,有什么方法可以把所有正在运行的进程移除呢? 40、bash shell 中的 hash 命令有...
  • 2021年前端面试题及答案

    万次阅读 多人点赞 2020-02-11 19:29:34
    前端面试汇总(2020年) 一 大纲 1、前言 2、前端工程化 3、前端设计模式 ...9、前端技术问题 前言 由于新冠肺炎疫情,现在成天呆在家里,加上也要准备面试,就在家里看面试题...
  • C++面试题汇总 (一)

    万次阅读 多人点赞 2019-06-27 08:54:39
    由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以及一个能完成清理与...
  • js面试题

    千次阅读 多人点赞 2019-04-09 19:42:32
    引用数据类型存储在堆(heap)中的对象,占据空间大、大小不固定,如果存储在中,将会影响程序运行的性能; 引用数据类型在中存储了指针,该指针指向堆中该实体的起始地址。 当解释器寻找引用值时,会首先检索...
  • 任务和返回 一个应用程序当中通常都会包含很多个Activity,每个Activity都应该设计成为一个具有特定的功能,并且可以让用户进行操作的组件。另外,Activity之间还应该是可以相互启动的。比如,一个邮件应用中可能...
  • Android 任务和返回详解

    千次阅读 2016-07-18 16:30:45
    Android 管理任务和返回的方式(如上所述,即:将所有连续启动的 Activity 放入同一任务和“后进先出”堆栈中)非常适用于大多数应用,而您不必担心 Activity 如何与任务关联或者如何存在于返回中。 但是,您...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 127,404
精华内容 50,961
关键字:

任务栈接单