敞开成长之旅!这是我参与「日新方案 12 月更文挑战」的第22天

首要,咱们知道,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

Android任务栈机制详解

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

1.2 singleTop

假如指定发动Activity为singleTop形式,那么在发动时,体系会判断当时栈顶Activity是不是要发动的Activity,假如是则不创立新的的Activity而直接引证这个Activity;假如不是则创立新的Activity。 实践代码验证 咱们在第一个样例的基础代码上,把第三个activity使命栈形式改为singleTop,相同的跳转逻辑,1-2-3-3,运转检查一下使命栈信息

Android任务栈机制详解

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,运转检查一下使命栈信息

Android任务栈机制详解

1.4 singleInstance

singleInstance这种形式和运用阅览器工资类似。在多个体系拜访阅览器时,假如当时阅览器没有翻开,则翻开阅览器,否则会在当时翻开的阅览器中拜访。申明为singleInstance的Activity会出现在一个新的使命栈中,而且这个使命栈只会存在一个Activity。 实践代码验证 咱们在第一个样例的基础代码上,把第三个activity使命栈形式改为singleInstance,相同的跳转逻辑,1-2-3-3,运转检查一下使命栈信息

Android任务栈机制详解

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);

Android任务栈机制详解
可以看到,在一个使命栈中,即便重新发动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);

Android任务栈机制详解
这时肯定有小伙伴问了,这不就和singleTask一样的效果了吗?我很确认的告诉您,不是哦~~~,clear_top假如检测到栈中有实例存在,会清空栈内包含自身的以上所有activity,咱们看一下activity 1的log日志打印就知道了
Android任务栈机制详解
所以,这儿咱们知道一个关键点:这儿看出来了吧,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);

Android任务栈机制详解
从这儿可以看出,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 会销毁自身,这就行了。