美文网首页Android技术知识Android开发安卓面试宝典
【Android面试】Android任务栈机制详解

【Android面试】Android任务栈机制详解

作者: itbird01 | 来源:发表于2022-02-06 22:08 被阅读0次

    首先,我们知道,android有任务栈机制,启动任务栈的方式有xml中配置,还有就是通过intent设置flag去启动相应的activity。这里我们分三部分来介绍
    1.xml配置的几种方式详解
    2.intent flag启动的几种方式详解
    3.flag 与 xml 几种方式的区别和联系

    1.XML配置的几种方式详解

    Android开发者在AndroidMainifest文件中一共设计了四种启动模式,如下所示

    1.1 standard

    默认的启动模式,如果不指定Activity的启动模式,则使用这种方式启动Activity。这种启动模式每次都会创建新的实例,每次点击standard模式创建Activity后,都会创建新的MainActivity覆盖在原Activity上。
    实际代码验证
    我们实例代码验证一下,新建三个activity,xml中不配置任务栈方式(默认为标准栈),三个activity相互跳转,代码如下:

    package com.itbird.task;
    
    import android.content.Intent;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import com.itbird.R;
    import com.itbird.bitmapOOM.BitmapUtils;
    import com.itbird.viewEvent.MyView;
    
    public class MainTestActivity extends AppCompatActivity {
    
        private static final String TAG = MainTestActivity.class.getSimpleName();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.task_test);
            Button button = findViewById(R.id.button);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(MainTestActivity.this, SecondTestActivity.class);
                    startActivity(intent);
                }
            });
        }
    
        @Override
        protected void onNewIntent(Intent intent) {
            Log.e(TAG, TAG + " onNewIntent");
            super.onNewIntent(intent);
        }
    
        @Override
        protected void onDestroy() {
            Log.e(TAG, TAG + " onDestroy");
            super.onDestroy();
        }
    }
    

    运行之后,跳转顺序为1-2-3-1,通过adb命令查看后台任务栈信息adb shell dumpsys activity activities | grep com.itbird

    image.png

    我们看到后台任务栈,的确是保持为同一个,而且activity实例一直是新建累加的。

    1.2 singleTop

    如果指定启动Activity为singleTop模式,那么在启动时,系统会判断当前栈顶Activity是不是要启动的Activity,如果是则不创建新的的Activity而直接引用这个Activity;如果不是则创建新的Activity。
    实际代码验证
    我们在第一个样例的基础代码上,把第三个activity任务栈模式改为singleTop,相同的跳转逻辑,1-2-3-3,运行查看一下任务栈信息

    大家可以发现,尽管跳转了两次3,但是栈中只有一个实例.png

    1.3 singleTask

    singliTask模式与singleTop模式类似,只不过singleTop是坚持栈顶元素是否是需要启动的Activity,而singleTask是检测整个Activity栈中是否存在需要启动的Activity。如果存在,则将该Activity置于栈顶,并将该Activity以上的Activity都销毁。不过这里是指在同一个App中启动这个singleTask的Activity,如果是其他程序以singleTask模式来启动这个Activity,那么它将创建一个新的任务栈。不过这里有一点需要注意的是,如果启动的模式为singleTask的Activity已经在后台一个任务栈中了,那么启动后,后台的这个任务栈将一起被切换到前台。
    实际代码验证
    我们在第一个样例的基础代码上,把第一个activity任务栈模式改为singleTask,相同的跳转逻辑,1-2-3-1,运行查看一下任务栈信息

    大家可以发现,任务栈中经过三次跳转,只剩一个了.png

    1.4 singleInstance

    singleInstance这种模式和使用阅览器工资类似。在多个系统访问阅览器时,如果当前阅览器没有打开,则打开阅览器,否则会在当前打开的阅览器中访问。申明为singleInstance的Activity会出现在一个新的任务栈中,而且这个任务栈只会存在一个Activity。
    实际代码验证
    我们在第一个样例的基础代码上,把第三个activity任务栈模式改为singleInstance,相同的跳转逻辑,1-2-3-3,运行查看一下任务栈信息

    大家可以发现,首先3是放在了新的栈中,其次跳转了两次,但是3的实例只有一个.png

    2,Intent flag启动的几种方式详解

    2.1 单独使用

    • FLAG_ACTIVITY_NEW_TASK
      加上 FLAG_ACTIVITY_NEW_TASK flag 后,启动一个 Activity 时,如果需要创建,被启动的 Activity 会在它需要的栈中创建。如 A 启动 B,B 会在 B 自己需要的栈中被创建(即 taskAffinity 指定的栈)。

    我们还是以之前的三个界面的例子,三个界面的xml配置启动栈方式都为标准栈,跳转顺序为1-2-3-1,跳转过程中使用FLAG_ACTIVITY_NEW_TASK flag,代码:

        Intent intent = new Intent(MainTestActivity.this, SecondTestActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    
    可以看到,在一个任务栈中,即使重新启动1,也是新建实例1.png
    可以看到,在一个任务栈中,即使重新启动1,也是新建实例1,也就是说,这个Flag只是去找寻亲和属性的栈或者新建栈,并不对栈内的实例进行复用、清空等操作。这里看出来了吧,FLAG_ACTIVITY_NEW_TASK != singleTask哦,网上有很多误人子弟的文章,大家还是自己实践出真知吧
    • FLAG_ACTIVITY_CLEAR_TOP
      我们还是以之前的三个界面的例子,三个界面的xml配置启动栈方式都为标准栈,跳转顺序为1-2-3-1,跳转过程中使用FLAG_ACTIVITY_CLEAR_TOP flag,代码:
        Intent intent = new Intent(MainTestActivity.this, SecondTestActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(intent);
    
    好神奇,只剩余一个实例1了.png
    这时肯定有小伙伴问了,这不就和singleTask一样的效果了吗?我很确定的告诉您,不是哦~~~,clear_top如果检测到栈中有实例存在,会清空栈内包含本身的以上所有activity,我们看一下activity 1的log日志打印就知道了
    看到了吗,实例1过程中被销毁再重建了.png
    所以,这里我们知道一个关键点:这里看出来了吧,FLAG_ACTIVITY_CLEAR_TOP != singleTask哦,网上有很多误人子弟的文章,大家还是自己实践出真知吧
    • FLAG_ACTIVITY_SINGLE_TOP
      我们还是以之前的三个界面的例子,三个界面的xml配置启动栈方式都为标准栈,跳转顺序为1-2-3-3,跳转过程中使用FLAG_ACTIVITY_SINGLE_TOP flag,代码:
        Intent intent = new Intent(MainTestActivity.this, SecondTestActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        startActivity(intent);
    
    尽管跳转了两次3,但是只有一个实例.png
    从这里可以看出,FLAG_ACTIVITY_SINGLE_TOP == singleTop哦

    2.2 组合使用

    针对于组合使用,我们直接说结论吧,依然是上面的例子,很好验证

    • FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_SINGLE_TOP
      activity 在前台(当前显示的栈的栈顶),不创建,它自己 onNewIntent 被调用;activity 不在前台的情形下,activity 需要的栈存在,在该栈中创建一个 activity 或将该栈移至前台(它自己 onNewIntent 被调用),activity 需要的栈不存在,创建一个它需要的栈,再创建 activity

    • FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TOP
      activity 在它需要的栈里存在,它上面的 activity 会出栈,它自己 finish 后重建
      activity 在它需要的栈里不存在,在它需要的栈里创建
      所以此处备注:FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TOP != singleTask

    • FLAG_ACTIVITY_CLEAR_TOP + FLAG_ACTIVITY_SINGLE_TOP
      activity 在前台(当前显示的栈的栈顶),不创建,它自己 onNewIntent 被调用;activity 不在前台的情形下,activity 在它需要的栈里存在,它上面的 activity 会出栈,它自己 onNewIntent 被调用,activity 在它需要的栈里不存在,在它需要的栈里创建。
      所以此处备注:FLAG_ACTIVITY_SINGLE_TOP + FLAG_ACTIVITY_CLEAR_TOP == singleTask

    3.flag 与 xml 几种方式的区别和联系

    其实相关区别和联系在上面已经基本都说过了,这里用等式简单总结一下:
    FLAG_ACTIVITY_NEW_TASK != singleTask
    FLAG_ACTIVITY_CLEAR_TOP != singleTask
    FLAG_ACTIVITY_NEW_TASK + FLAG_ACTIVITY_CLEAR_TOP != singleTask
    FLAG_ACTIVITY_SINGLE_TOP + FLAG_ACTIVITY_CLEAR_TOP == singleTask
    FLAG_ACTIVITY_SINGLE_TOP == singleTop
    当然这些结论都是基于最初的activity是标准栈的前提,如果将activity最初xml配置改为其他启动栈模式,结论可能有些就发生了一点点的改变。
    我们不需要死记硬背这些知识,这些知识点最好各位结合自己的实践Demo验证一波,同时记住一点,FLAG_ACTIVITY_NEW_TASK 只是针对于栈的描述,FLAG_ACTIVITY_CLEAR_TOP 会销毁本身,这就行了。

    相关文章

      网友评论

        本文标题:【Android面试】Android任务栈机制详解

        本文链接:https://www.haomeiwen.com/subject/lcgskrtx.html