Android Activity的启动模式

前言

Activity的启动模式是重要的一块内容,在面试中,面试官常常会考Activity启动模式。Activity的启动模式共有四种,standard、singleTop、singleTask、singleInstance。让我们一探究吧。

1.standard

standard是Activity的默认启动模式也就是标准启动模式,在不特殊指定情况下,所有的Activity都是默认使用这种启动模式。我们知道Activity是通过返回栈来管理活动的,每创建一次Activity就会把它压入栈中,遵循先进后出原则,后进来的先释放。默认启动模式下,系统每次都会新的Activity实例,然后压入栈中。
在这里插入图片描述
用实际代码来体验一下,因为是默认启动模式,所以我们不需要在清单文件中声明,直接添加测试代码。布局文件就一个按钮,java类中声明这个按钮并添加跳转到自身Activity的点击方法。
以下就是activity_main.xml文件代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <TextView
        android:text="这是第一个activity"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
    </TextView>

    <Button
        android:id="@+id/button"
        android:text="跳转按钮"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
    </Button>
</LinearLayout>

然后就是java代码:


public class MainActivity extends AppCompatActivity {
    private Button mButton;
    private static final String TAG="MainActivityLog";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.v(TAG,this.toString());
        setContentView(R.layout.activity_main);
        initView();//加载布局文件
        onClick();//管理所有的点击方法
    }
    public void initView(){
        mButton=findViewById(R.id.button);
    }
    public void onClick(){
        //按钮点击产生新的activity
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent=new Intent();
                intent.setClass(MainActivity.this,MainActivity.class);
                startActivity(intent);
            }
        });
    }
}

当我们点击两次跳转按钮后,就会看到下面的打印日志:
在这里插入图片描述
第一行打印的,就是我们第一次启动的时候Activity执行的创建方法,后面两个就是我们点击两次跳转按钮后,产生了新的Activity对象。而且都是不同的,看它们打印出的ID也是不同。也就是说,返回栈中存在三个不同的Activity实例,要按三次BACK键(返回键)才可以退出程序。默认启动模式就是每次都会产生新的Activity实例。

2.singleTop

singleTop就很好理解了,看到单词Top是“顶端”、“上面”的意思,就是当前返回栈的栈顶的实例就是我们要的Activity实例,就直接使用就可以了,不需要再重新创建。比如我们当前要跳转到Activity4这个实例,返回栈顶端已经是Activity4了,就直接拿来用就可以了,不需要再创建。记住在这个启动模式下,必须在栈顶才直接使用,如果Activity4不在栈顶,则会创建新的Activity4实例。
在这里插入图片描述
接下来看看测试代码:

 		<activity 
            android:name=".MainActivity"
            android:launchMode="singleTop">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

在AndroidManifest.xml文件的Activity注册中添加android:launchMode="singleTop"就可以实现启动模式的指定。java代码则跟上面standard启动模式的代码一样。现在再按几次跳转按钮。看看效果:
在这里插入图片描述
可以看到,无论按多少次跳转按钮,都不会创建新的Activity实例,而是直接使用已经在栈顶的实例。然后按一次BACK键就可以直接退出程序了,这就是singleTop启动模式的理解和使用。

3.singleTask

singleTask看到有一个单词Task,Task就是栈的意思。singleTask模式会首先检测返回栈是否存在当前Activity实例,如果存在,会释放掉该Activity上面的所有Activity实例然后再使用,不存在的时候则会创建新的Activity实例。记住是整个栈中,无论是在栈顶还是在哪里。
在这里插入图片描述
我们在SecondActivity中添加一个跳转到MainActivity按钮,我们的测试流程就是从MainActivity跳转到SecondActivity,然后再从SecondActivity跳转到MainActivity。看一下代码。
先是设置MainActivity的启动模式是singleTask:

 		<activity
            android:name=".MainActivity"
            android:launchMode="singleTask">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

MainActivity还是原来的代码,跳转到SecondActivity,然后在SecondActivity添加跳转按钮和跳转方法。


public class SecondActivity extends AppCompatActivity {
    private Button mButton;
    private static final String TAG="MainActivityLog";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        initView();//加载布局文件
        onClick();//管理所有的点击方法
    }
    public void initView(){
        mButton=findViewById(R.id.button);
    }
    public void onClick(){
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent=new Intent();
                intent.setClass(SecondActivity.this,MainActivity.class);
                startActivity(intent);
            }
        });
    }
}

测试流程是这样的,跳转到另一个Activity再跳回来,一直执行来回跳的操作。看测试效果:
在这里插入图片描述
可以看到因为SecondActivity是标准模式,会每次都会产生一个新的实例,而MainActivity不会,因为设置了singleTask启动模式,所以栈中只有一个实例,不会重新创建。这就是singleTask模式的理解和使用。

4.singleInstance

singleInstance是这个四个中稍微复杂的一个,但也好理解。想实现两个程序公用一个Activity,就需要用到singleInstance这个模式。在这种模式下会有一个单独的返回栈来管理设置了singleInstance模式的这个Activity实例,不管哪个应用程序来访问这个Activity,都会共用一个返回栈,这样就实现了共享Activity实例的问题。
在这里插入图片描述
结合代码实例来讲,先看看正常情况下是不是使用一个栈,设置了三个Activity,三个Activity都是默认启动模式,打印当前栈的id,也就是getTaskId()可以获得当前栈的ID。
测试流程:MainActivity->SecondActivity->ThreeActivity 一路跳转下来。
看其中一个类的代码,其它的也是如此,点击事件跳转的Activity不一样而已。


public class ThreeActivity extends AppCompatActivity {
    private Button mButton;
    private static final String TAG="ThreeActivityLog";

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_three);
        Log.v(TAG,"Task id is "+getTaskId());
        setContentView(R.layout.activity_second);
        initView();//加载布局文件
        onClick();//管理所有的点击方法
    }
    public void initView(){
        mButton=findViewById(R.id.button);
    }
    public void onClick(){
        //按钮点击产生新的Activity
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent=new Intent();
                intent.setClass(ThreeActivity.this,MainActivity.class);
                startActivity(intent);
            }
        });
    }
}

效果图:
在这里插入图片描述
打印说明了,三个Activity实例都在同一个栈中。
这次我们把SecondActivity设置为我们本次的singleInstance启动模式。

  		<activity
            android:name=".SecondActivity"
            android:launchMode="singleInstance">
        </activity>

然后再执行MainActivity->SecondActivity->ThreeActivity 点击此时,看打印日志。
在这里插入图片描述
可以看到设置了singleInstance启动模式的SecondActivity所在栈跟MainActivity和ThreeActivity是不一样的。因为SecondActivity使用了单独的返回栈。还有一个重要的说明,那就是当你在ThreeActivity按下BACK(返回键)的时候,会直接回到MainActivity,而不是SecondActivity。然后再按BACK,才会回到SecondActivity。这是因为ThreeActivity和MainActivity是同一个返回栈,ThreeActivity释放掉再释放MainActivity,当前返回栈就空了,于是就显示了另一个返回栈的Activity,即SecondActivity。再按一次BACK,SecondActivity实例出栈,当前返回栈也空了,程序就退出了。以上就是singleInstance启动模式的理解和使用。

参考文章

郭霖《第一行代码》(第2版)64页到70页

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值