Android 任务栈机制详解

1 XML配置的几种方式详解 首先,我们知道,android有任务栈机制,启动任务栈的方式有xml中配置,还有就是通过intent设置flag去启动相应的act

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

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

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

1.2 singleTop

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

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,运行查看一下任务栈信息

1.4 singleInstance

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

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,也就是说,这个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);

这时肯定有小伙伴问了,这不就和singleTask一样的效果了吗?我很确定的告诉您,不是哦~~~,clear_top如果检测到栈中有实例存在,会清空栈内包含本身的以上所有activity,我们看一下activity 1的log日志打印就知道了

所以,这里我们知道一个关键点:这里看出来了吧,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);

从这里可以看出,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 任务栈机制的资料请关注好代码网其它相关文章!