Android学习之Activity的启动模式

一、引言

很多朋友去面试的时候,可能都会被问到这样一个问题:

请给我详细描述一下Activity的生命周期,及其相关的启动模式。

生命周期我倒是知道一点,启动模式又是个什么玩意?如果你没有事先准备的话,可能会被问个措手不及。那么接下来,就让我带你深入的了解这个知识点。

(关于Activity的生命周期,在之前的文章中已经讲过了,感兴趣的小伙伴点击下面的链接,就可以查询到。)

《Android学习之浅谈Activity的生命周期》

二、四种启动方式

Activity中一共有四种启动模式,分别为:

  1. standard 标准启动模式
  2. singleTop
  3. singleTask
  4. singleInstance

它们主要是在AndroidMainifest文件中,通过给activity标签指定android:launchMode属性来设置。

在这里我们要了解一个概念,android是通过返回栈来管理活动的。而栈是一个后进先出的数据结构,所以每当我们创建一个新活动,它都会自动放在栈顶。当我们使用finish()销毁这个活动时,位于栈顶的活动就会出栈,前一个入栈的活动,就会重新出现在栈顶。我们的系统每次都会将栈顶的活动展现给用户。

了解了这些以后,我们来对这四种启动方式深入解析吧~

三、standard

standard是活动默认的启动方式。每当你创建一个新活动,它就会在返回栈中入栈,并处于栈顶的位置。而且它不会管你栈中是否已经存在这个实例,每次启动都会创建一个新的实例。

下面我们进行代码演示分析:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("MainActivity",this.toString());
        setContentView(R.layout.activity_main);

        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(MainActivity.this,MainActivity.class));
            }
        });
    }
}

在这里我们创建了一个按钮,用于在两个MainActivity之间的转跳。如果按照正常的来说,这个MainActivity已经被创建了,我们不管怎么转跳,都不会产生新的实例才对,但是事实并不是这样。我们查看下打印信息。
在这里插入图片描述
可以看到,我一共点击了两次按钮,它又重新创建了两个实例。这样你按返回键时,也需要点击三次才可以完全退出。

四、singleTop

了解了standard模式后,你可能会觉得不太合理对吧?为啥我已经存在了,还需要重新创建。但这是系统默认的启动方式,你也可以进行相关的修改。比如这种SingleTop模式。当你的返回栈栈顶已经是该活动,就可以直接进行调用,就不会重新创建新的实例

下面我们进行代码演示:

首先我们在AndroidMainifest文件中,修改其启动模式。

        <activity
            android:name=".MainActivity"
            android:launchMode="singleTop">

然后我们继续运行这个程序,会发现你不管点击多少次,都不会产生新的实例。因为这时候MainActivity已经处于栈顶了。
在这里插入图片描述
但是这种启动方式,还是会存在着一定的问题。我们首先创建一个点击事件,让MainActivity转跳到SecondActivity。

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("MainActivity",this.toString());
        setContentView(R.layout.activity_main);

        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(MainActivity.this,SecondActivity.class));
            }
        });
    }
}

然后再在SecondActivity中,转跳回MainActivity

public class SecondActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("SecondActivity",this.toString());
        setContentView(R.layout.activity_second);

        findViewById(R.id.button_1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(SecondActivity.this,MainActivity.class));
            }
        });
    }
}

这时候查看打印信息:
在这里插入图片描述
这时候你会发现,它又重新创建了一个MainActivity,这是为什么呢?

其实很简单,因为刚开始MainActivity在栈顶,但当你转跳到另一个界面时,栈顶就会变成SecondActivity,所以这时候会重新创建一个MainActivity。

五、singTask

这个启动方式,就可以很好的解决之前出现的一切问题。因为当你使用这个启动方式,每一次都会在返回栈中检查是否存在该活动的实例,如果发现已存在,那么就会直接调用,并且将这个活动上的所有活动全部出栈。如果没有发现,那么就会创建一个新的实例。

下面进行代码演示:

首先我们在MainActivity中添加一个OnRestart方法:

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.d("MainActivity","OnRestart");
    }

在SecondActivity中添加一个OnDestroy方法:

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d("SecondActivity","OnDestroy");
    }

执行后发现:
在这里插入图片描述

从这个打印信息我们可以得出,当刚开始启动时,MainActivity处于栈顶,转跳到SecondActivity以后,MainActivity就在底下了,这时候再返回MainActivity,就会将SecondActivity出栈,并重新调用MainActivity,也不要创建新的实例。按一次返回键就可以退出了。

六、SingInstance

这个启动方式就厉害了。它会给你这个活动创建一个新的返回栈,单独保存。这样有什么意义呢?这样可以实现其他程序和我们的程序,共享这个活动的实例。

下面进行代码演示:

首先我们将SecondActivity的启动方式改为singInstance

然后在MainActivity中添加一个打印信息:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("MainActivity","Task id is" + getTaskId());
        setContentView(R.layout.activity_main);

        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(MainActivity.this,SecondActivity.class));
            }
        });
    }

在SecondActivity中也添加一个打印信息:

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("SecondActivity","Task id is" + getTaskId());
        setContentView(R.layout.activity_second);

在ThirdActivity中也添加一个打印信息:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d("ThirdActivity","Task id is" + getTaskId());
        setContentView(R.layout.activity_third);

运行以后输出打印信息:
在这里插入图片描述
可以看出MainActivity和ThirdActivity在一个栈中,SecondActivity在另一个栈中。

但是当我们按下返回键以后,会发现直接从ThirdActivity直接返回到MainActivity,然后再按一下返回,又会返回到SecondActivity,最后按一下back才能退出。为什么会出现这种情况呢?其实很简单,因为MainActivity和ThirdActivity处于一个栈中,当ThirdActivity出栈后,MainActivity就会出现在栈顶。等MainActivity出栈后,这个栈就空了,所以调用另一个栈。也就是SecondActivity所在的栈。最后按一下返回,所以的栈都空了,所以退出程序。

七、小结

Activity的四种启动方式就先讲到这里吧。我觉得整个文章还是比较好理解的,而且所有的步骤都是有代码演示,也比较的清晰。最后希望这篇文章能够帮助到大家,一起共同进步呀!

你可能感兴趣的:(Android学习,java,android)