Activity启动模式详解

Posted zhangjinhuang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Activity启动模式详解相关的知识,希望对你有一定的参考价值。

众所周知,android给我们提供了standardsingleTopsingleTasksingleInstance 4种Activity的启动模式,其中:

standard:标准模式,即默认启动模式;

singleTop:顶单例模式,即要求实例处于栈顶;

singleTask:内单例模式,即要求栈中只有一个实例;

singleInstance:全局单例模式;

接下来将会对以上4种加载模式进行讲解。

1standard模式

每次通过这种模式启动目标Activity时,android总会为目标Activity创建一个新的实例,并将该实例添加到当前的任务栈中,这种模式不会启动新的任务栈,新创建的Activity实例将被添加到原有的任务栈中。如:

public class StandardActivity extends AppCompatActivity 

    private TextView tv_content;
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_standard);
        tv_content = (TextView) findViewById(R.id.tv_content);
        tv_content.setText("当前Activity为:"+"\\n"
                +this.toString()
                +"\\n"+" TaskId为:"+this.getTaskId());
    

    public void skip2StandardActivity(View view)
        Intent intent = new Intent(StandardActivity.this,StandardActivity.class);
        startActivity(intent);
    
运行程序,可以发现每次点击StandardActivity都会创建一个新的StandardActivity实例,在控制台中输入: adb shell dumpsys activity 然后回车可以看到 Activity 的栈情况

需要注意的是,Standard加载模式无须配置目标ActivitylaunchMode属性,目标Activity会默认采用standard加载模式。


2singleTop模式

singleTop模式与standard模式基本相似,唯一不同的是,当将要被启动的目标Activity已经处于任务栈栈顶时,系统不会重新创建目标Activity的实例,而是直接复用已有的Activity,当然,如果将要被启动的目标Activity没有位于任务栈栈顶的话,此时系统会重新目标Activity,并将创建的新的Activity实例添加到任务栈中(此时与standard加载模式相同)。如:

public class StandardActivity extends AppCompatActivity 

    private TextView tv_content;
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_standard);
        tv_content = (TextView) findViewById(R.id.tv_content);
        tv_content.setText("当前Activity为:"+"\\n"
                +this.toString()
                +"\\n"+" TaskId为:"+this.getTaskId());
    

    public void skip2StandardActivity(View view)
        Intent intent = new Intent(StandardActivity.this,StandardActivity.class);
        startActivity(intent);
    

    public void skip2SingleTopActivity(View view)
        Intent intent = new Intent(StandardActivity.this,SingleTopActivity.class);
        startActivity(intent);
    

目标SingleTopActivity 的主要代码如下所示:

public class SingleTopActivity extends AppCompatActivity 

    private TextView tv_content;
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_standard);
        tv_content = (TextView) findViewById(R.id.tv_content);
        tv_content.setText("当前Activity为:"+"\\n"
                +this.toString()
                +"\\n"+" TaskId为:"+this.getTaskId());
    
    public void skip2StandardActivity(View view)
        Intent intent = new Intent(SingleTopActivity.this,StandardActivity.class);
        startActivity(intent);
    

    public void skip2SingleTopActivity(View view)
        Intent intent = new Intent(SingleTopActivity.this,SingleTopActivity.class);
        startActivity(intent);
    
另外,需要在 AndroidManifest 清单文件中为目标 SingleTopActivity 配置 launchMode 属性,并将其指定为 singleTop ,如下所示:

<activity android:name=".SingleTopActivity"
    android:launchMode="singleTop"/>
此时,运行程序可以发现,当在 StandardActivity 中点击 SingleTopActivity 按钮时会创建一个 SingleTopActivity 的实例,当在 SingleTopActivity 中点击 SingleTopActivity 按钮时,由于 SingleTopActivity 已经在任务栈的栈顶,因此不会再创建新的实例,当然,如果在 SingleTopActivity 中点击 StandardActivity 按钮回到 StandardActivity 界面时,此时再点击 SingleTopActivity 按钮,会发现,又创建了一个新的 SingleTopActivity 的实例。同样的,在控制台输入: adb shell dumpsys activity 命令可以查看 Activity 的任务栈情况如下所示:


3singleTask模式

采用singleTask加载模式的Activity在同一个任务栈内只有一个实例,当系统采用singleTask模式启动目标Activity时,可分为如下几种情况:

1)如果将要启动的目标Activity不存在,系统将会创建目标Activity的实例,并将它添加到任务栈的栈顶中;

2)如果将要启动的目标Activity已经位于任务栈的栈顶,此时与singleTop模式相同,系统不会重新创建新的目标Activity的实例,而是直接复用已有的Activity实例;

3)如果将要启动的目标Activity已经存在,但没有位于任务栈的栈顶,那么此时系统将会把位于该Activity上面的所有Activity移出任务栈,从而使得目标Activity处于任务栈的栈顶。如

public class StandardActivity extends AppCompatActivity 

    private TextView tv_content;
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_standard);
        tv_content = (TextView) findViewById(R.id.tv_content);
        tv_content.setText("当前Activity为:"+"\\n"
                +this.toString()
                +"\\n"+" TaskId为:"+this.getTaskId());
    

    public void skip2StandardActivity(View view)
        Intent intent = new Intent(StandardActivity.this,StandardActivity.class);
        startActivity(intent);
    
    public void skip2SingleTaskActivity(View view)
        Intent intent = new Intent(StandardActivity.this,SingleTaskActivity.class);
        startActivity(intent);
    
SingleTaskActivity 的代码如下所示:

public class SingleTaskActivity extends AppCompatActivity 

    private TextView tv_content;
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_standard);
        tv_content = (TextView) findViewById(R.id.tv_content);
        tv_content.setText("当前Activity为:"+"\\n"
                +this.toString()
                +"\\n"+" TaskId为:"+this.getTaskId());
    
    public void skip2StandardActivity(View view)
        Intent intent = new Intent(SingleTaskActivity.this,StandardActivity.class);
        startActivity(intent);
    

    public void skip2SingleTaskActivity(View view)
        Intent intent = new Intent(SingleTaskActivity.this,SingleTaskActivity.class);
        startActivity(intent);
    
当然,跟 singleTop 模式一相,同样需要在 AndroidManifest 清单文件中跟 SingleTaskActivity 添加 launchMode 属性并将其指定为 singleTask ,如下所示:

<activity android:name=".SingleTaskActivity"
    android:launchMode="singleTask"/>
程序运行后,在 StandardActivSity 中点击 SingleTaskActivity 按钮跳转到 SingleTaskActivity 时会创建一个 SingleTaskActivity 的实例,此时点击 StandardActivity 按钮跳转到 StandardActivity 中,在多次点击 StandardActivity 后,再点击 SingleTaskActivity 按钮会发现,此时并没有创建新的 SingleTaskActivity 的实例,并且原先位于 SingleTaskActivity 实例上面的所有 StandardActivity 的实例都消失了。



4singleInstance模式

singleInstance这种加载模式可以保证系统无论从哪个任务栈中启动目标Activity,都只会创建一个目标Activity的实例,并会使用一个全新的任务栈来装载该Activity的实例。

当以singleInstance模式启动目标Activity时,可分为如下两种情况:

1)如果将要启动的目标Activity不存在,系统会先创建一个全新的任务栈,再创建目标Activity的实例,并将它加入到新的任务栈的栈顶;

2)如果将要启动的目标Activity已经存在,无论它位于哪个任务栈中,系统都将会把该Activity所在的任务栈转到最前面,从而使该Activity显示出来。

需要注意的是采用singleInstance模式加载的Activity总是位于任务栈的栈顶,并且加载的Activity所在的任务栈中只包含该Activity。代码如下所示:

public class StandardActivity extends AppCompatActivity 

    private TextView tv_content;
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_standard);
        tv_content = (TextView) findViewById(R.id.tv_content);
        tv_content.setText("当前Activity为:"+"\\n"
                +this.toString()
                +"\\n"+" TaskId为:"+this.getTaskId());
    

    public void skip2StandardActivity(View view)
        Intent intent = new Intent(StandardActivity.this,StandardActivity.class);
        startActivity(intent);
    
    public void skip2SingleInstanceActivity(View view)
        Intent intent = new Intent(StandardActivity.this,SingleInstanceActivity.class);
        startActivity(intent);
    
SingleInstanceActivity的代码如下所示:

<span style="font-size:12px;">public class SingleInstanceActivity extends AppCompatActivity 

    private TextView tv_content;
    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_standard);
        tv_content = (TextView) findViewById(R.id.tv_content);
        tv_content.setText("当前Activity为:"+"\\n"
                +this.toString()
                +"\\n"+" TaskId为:"+this.getTaskId());
    
    public void skip2StandardActivity(View view)
        Intent intent = new Intent(SingleInstanceActivity.this,StandardActivity.class);
        startActivity(intent);
    
    public void skip2SingleInstanceActivity(View view)
        Intent intent = new Intent(SingleInstanceActivity.this,SingleInstanceActivity.class);
        startActivity(intent);
    
</span><span style="font-size:14px;">
</span>
AndroidManifest 清单文件中给 SingleInstanceActivity 添加 launchMode 属性并将其指定为 singleInstance ,代码如下所示:

<activity android:name=".SingleInstanceActivity"
    android:launchMode="singleInstance"/>
运行程序可以看出,当在 StandardActivity 中点击 SingleInstanceActivity 按钮时,如果 SingleInstanceActivity 实例不存在,则会先创建一个 SingleInstaceActivity 的实例,在 SingleInstaceActivity 中点击 StandardActivity 按钮回到 StandardActivity 后,连续点击几次 StandardActivity 按钮进行跳转后再点击 SingleInstanceActivity 按钮会发现 SingleInstanceActivity 并没有再次创建新的实例。同样的,在控制台通过: adb shell dumpsys activity 命令可以查看 Task 栈的情况,从结果中可以发现点击 SingleInstanceActivity 按钮时新创建了一个任务栈并将新创建的 SingleInstanceActivity 的实例添加到了该任务栈中。



此时,关于Activity的启动模式就算是已经讲解完了。

 源码

以上是关于Activity启动模式详解的主要内容,如果未能解决你的问题,请参考以下文章

Android Activity的4种启动模式详解(示例)

Activity启动模式详解

Activity启动模式详解

android Activity的启动模式 作用简析+demo详解

Activity的启动模式与flag详解

Activity详解四 activity四种加载模式