Android——活动的启动模式

活动的启动模式总共有四种:standard、singleTop、singleTask、singleInstance。若要修改活动的启动模式,可以在AndroidManifest.xml中的activity标签添加android:launchMode属性来选择启动模式。若没有声明活动的启动模式,那么活动的启动模式默认为standard。
下面来分别讲解四种启动模式:

一、standard启动模式(标准模式)

Standard是活动默认的启动模式,在不进行指定的情况下,所有活动都会自动使用这种启动模式。
众所周知Android时使用返回栈来管理活动的,在standard模式下,每启动一个Activity,他就会在返回栈中入栈并处于栈顶,而在创建新的活动的时候,系统并不会检测新启动的Activity是否在返回栈中、是否在栈顶,而是简单地直接创建。因此,若在一个Activity中创建一个启动其本身的一个开关,在点击后,系统将会创建一个新的Activity,并且覆盖在当前Activity上面,而退出上面的Activity后,显示出来的则是上一个被覆盖的Activity。

实践:
1、新建一个名为FirstActivity的项目,修改其中的xml布局文件,添加一个文本为FirstActivity的Button控件。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/button1"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:textAllCaps="false"
        android:text="FirstActivity"
        />

</LinearLayout>

2、在FirstActivity.java文件中修改代码:在Activity每次跑onCreate和onRestart时打印该活动的信息,并在onCreate中注册按钮点击事件,点击按钮后跳转同一活动。

public class FirstActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d("FirstActivity", "onCreate():" + this.toString());//每次创建该活动时打印
        Button button1 = (Button) findViewById(R.id.button1);
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(FirstActivity.this, FirstActivity.class);
                startActivity(intent);
            }
        });
    }

    @Override
    protected void onRestart() {
    	Log.d("FirstActivity", "onRestart():" + this.toString());//每次恢复该活动时打印
    	super.onRestart();
    }

}

3、运行后如下图:
在这里插入图片描述
然后打开Android Studio中的Logcat查看打印。
先点击两次FirstAcitvity 按钮,会发现每次打印的FirstActivity后面的编号都不一样,即代表每次都是启动了新的活动,然后点击了三次返回键,最终才退出活动回到桌面,而看打印发现点击第一次返回后活动的编号与第二次启动的活动编号相同,而点击第二次返回后活动的编号与第三次启动的活动编号相同。
在这里插入图片描述
总结:
Standard启动模式下,同一个Activity可以有多个实例,因为系统不会检测返回栈中是否拥有该Activity的实例,无论该Activity是否在栈顶。

Standard启动模式示意图:

Standard启动模式

二、singleTop启动模式(栈顶复用模式)

若Activity的启动模式设置为singleTop,那么在启动新的Activity的时候如果发现返回栈的栈顶已经是该Activity,则不会再去创建新的活动,而是直接使用它。
但是需要注意的是,在启动新的Activity的时候,系统只会判断栈顶的Activity是否与之相同,换句话说就是,如果有个相同的Activity在返回栈中但是不在栈顶,那么系统仍然会创建一个新的Activity。

实践:
1、修改AndroidManifest.xml中FirstActivity的启动模式
在这里插入图片描述
2、
情况一:栈顶的活动和要启动的活动是同一个
运行后再FirstActivity中点击按钮,会发现活动没有做任何操作,而Logcat 中的打印也只有刚打开app时的一次打印
在这里插入图片描述
这就是因为系统检测到返回栈顶的活动和要启动的活动是同一个,所以它就不会创建新的活动而是直接使用栈顶活动

情况二:栈顶的活动和要启动的活动不是同一个
这时候需要创建一个新的活动,命名为SecondActivity,首先在布局中添加一个button控件,然后在SecondActivity中注册button按钮点击事件,点击button时跳转到FirstActivity。
在这里插入图片描述
在这里插入图片描述
接着修改FirstActivity里的打印内容和button点击事件的Intent。
在这里插入图片描述
运行后先点击FirstActivity中的button再点击SecondActivity中的button。
在这里插入图片描述
看Logcat可知系统先创建了一个FirstActivity,然后创建了一个SecondActivity,接着创建了一个新的FirstActivity。

singleTop启动模式示意图:

栈顶活动与新启动活动相同
在这里插入图片描述
栈顶活动与新启动活动不同
在这里插入图片描述
应用场景:在通知栏点击收到的通知,然后会启动一个Activity,这个Activity就可以使用singleTop模式,在启动的时候检测是否栈顶的Activity就是要启动的Activity,否则每次点击都会新建一个Activity。

三、singleTask启动模式(栈内复用模式)

singleTop模式能够很好地解决重复创建栈顶活动的问题,但是如果重复的活动不在栈顶,那么singleTop就不能检测出来,还是会创建多个同一活动的实例。而singleTask启动模式就能很好地解决这个问题。
当Activity的启动模式设置为singleTask的时候,每次系统创建新的活动之前,都会检测返回栈中是否存在相同活动的实例,若不存在则直接创建新的活动,否则将返回栈中已存在的活动实例上面的所有活动出栈,然后直接使用该活动实例。

实践:
1、在AndroidManifest.xml中修改启动模式
在这里插入图片描述
2、在SecondActivity中重写onDestory()方法,修改onCreate()方法(添加打印):

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.secondlayout);
    Log.d("Activity", "SecondActivity: onCreate " + this.toString());//每次创建该活动时打印
    Button button1 = (Button) findViewById(R.id.button2);
    button1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(SecondActivity.this, FirstActivity.class);
            startActivity(intent);
        }
    });
}

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

3、运行app,先点击FirstActivity中的按钮再点击SecondActivity中的按钮,查看logcat
在这里插入图片描述
由此可知当返回栈中包含需要启动的活动时,该活动会Restart并且将其上面的活动销毁。

singleTask启动模式示意图:

在这里插入图片描述
应用场景:大多数App的主页。在大多数的App中,我们在主页点击返回键就代表着退出这个应用,在我们刚打开app进入到主界面的时候,主界面的Activity处于栈底,后面不管我们打开多少界面,在返回主页的时候都应该将主界面上面的其他Activity都移除来使得主界面处于栈顶,这样就能保证用户在主页点击返回键的时候所有Activity都能够销毁。因此App的主页适合用singleTask模式。

四、singleInstance启动模式(单例模式)

不同于以上三种启动模式,设置为singleInstance启动模式的Activity会启用一个新的返回栈来管理这个Activity(其实如果singleTask模式指定了不同的taskAffinity,也会启动一个新的返回栈)。
那么singleInstance的实际应用场景是什么呢?
假如我们的程序中有一个Activity允许被其他程序调用,如果我们想我们的程序可以和其他程序共享这个Activity,前面说到的3种启动模式都不能解决这个问题,因为每个应用程序都会有自己的返回栈,同一个活动在不同的返回栈中入栈时必然是创建了新的实例。这时使用singleInstance启动模式就可以解决这个问题,因为在这种模式下会有一个单独的返回栈来管理这个活动,不管是哪个应用程序访问这个活动,都是在同一个返回栈中调用,也就解决了共享活动实例的问题。

实践:
1、新建ThirdActivity,在布局中添加一个Button控件
在这里插入图片描述
2、在ThirdActivity中注册Button点击事件,点击后跳转到FirstActivity(同时修改FirstActivity中按钮点击事件为跳转到SecondActivity,修改SecondActivity中按钮点击事件为跳转到ThirdActivity,此处只展示ThirdActivity代码)
修改FirstActivity、SecondActivity、ThirdActivity在onCreate中的打印,通过getTaskId()方法获取当前Activity所在返回栈

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.thirdlayout);
    Log.d("Activity", "ThirdActivity TaskId is:" + getTaskId());//每次创建该活动时打印
    Button button1 = (Button) findViewById(R.id.button3);
    button1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(ThirdActivity.this, FirstActivity.class);
            startActivity(intent);
        }
    });
}

@Override
protected void onRestart() {
    Log.d("Activity", "ThirdActivity onRestart()");//每次恢复该活动时打印
    super.onRestart();
}

3、在AndroidManifest.xml中设置SecondActivity的启动模式为singleInstance
在这里插入图片描述
4、运行app,依次点击FirstActivity、SecondActivity、ThirdActivity中的按钮,再点击两次返回键
5、查看logcat,可知FirstActivity和ThirdActivity在同一个Task,SecondActivity在另一个Task。
在这里插入图片描述

singleInstance启动模式示意图:

在这里插入图片描述
singleInstance相当于栈内复用模式(singleTask)的加强版,一旦该模式的Activity实例已经存在某个栈中,当需要创建一个该Activity时,就会直接重用该栈中的实例。
应用场景:呼叫来电界面。这种模式使用得比较少,在Launcher中可能会用到,或者你确定某个Activity只有一个实例的时候也可以使用。

拓展:
Activity的启动模式除了可以在AndroidManifest.xml文件中设置外,还可以在启动Activity时通过Intent的addFlags()方法进行设置:

Intent.addFlags(int flags)

Activity的Flags有20种,这里我简单说一下常用的三种:
(1)FLAG_ACTIVITY_NEW_TASK 效果与singleTask模式一致
(2)FLAG_ACTIVITY_SINGLE_TOP 效果与singleTop模式一致
(3)FLAG_ACTIVITY_CLEAR_TOP 具有这个标记的Activity,当它启动时,在同一个任务栈中位于它上面的所有Activity都要出栈。如果该Activity同时是singleTask模式,若栈中已经存在这个Activity,那么在该Activity上面的所有Activity都会出栈,并且调用该Activity的onNewIntent方法。如果该Activity是standard模式,那么该Activity和其上面的Activity全部出栈,然后创建新的Activity实例并压入栈。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值