什么是启动模式

简单来讲,就是指的安卓应用的开启模式,也就是安卓活动开启的策略。

为什么需要启动模式

1.生成APP被其他APP调用的Activity,例如浏览器应用,照相机应用。
2.有效避免生成重复页面,降低手机内存的利用率。
3.任务栈过深的时候,避免一直按返回键也退不回想要的页面。

安卓中的任务栈

任务栈,在安卓关键字中叫做 Task,是用来放置Activity实例的容器,顾名思义,以栈的形式进行存放,根据栈先进后出的性质,任务栈主要有2个基本操作:压栈和出栈,存放的Activity是不支持重新排序的,只能根据压栈和出栈操作更改Activity的顺序。
当启动一个App应用的时候,系统会默认创建一个对应的Task,用来放置根Activity。默认启动Activity会放在同一个Task中,新启动的Activity会被压入启动它的那个Activity的栈中,并且显示它。当用户按下回退键时,这个Activity就会被弹出栈,按下Home键回到桌面,再启动另一个应用,这时候原来那个Task就被移到后台,成为后台任务栈,而刚启动的那个Task就被调到前台,成为前台任务栈,手机页面显示的就是前台任务栈中的栈顶元素。

安卓中,启动模式主要有四种(该图源于网络):

android开启活动 安卓活动启动器_任务栈

1 Standard 标准模式

说明:
Android创建Activity时的默认模式,假设没有为Activity设置启动模式的话,默认标准模式。每次启动一个Activity都会又一次创建一个新的实例入栈,无论这个实例是否存在。即每个Activity都会新建一个实例,当一个页面被多次重复使用时,需要多次重复实例的创建
生命周期:
每次被创建的实例Activity 的生命周期符合典型情况,它的onCreate、onStart、onResume都会被调用。

在 AndroidManifest.xml 中 的MainActivity 中添加android:launchMode=“standard” 这样的配置,其实默认就是这个启动模式

<activity
            android:name=".MainActivity"
            android:launchMode="standard">
            <!--
            意图过滤器
            action:行为,为 MAIN 主行为
            category:为activity的种类 这里是 Launcher 即项目加载即执行
            -->
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

在 MainActivity 中构建一个自己访问自己的活动,使用 button1 进行监听

// 为按钮添加事件监听器
        button1.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                //接收来自其他页面的返回值
                Intent intent=new Intent(MainActivity.this,MainActivity.class);
                startActivity(intent);
            }
        });

则 初始化 时有以下的log文件
D/MainActivity: onCreate()com.example.example.MainActivity@75d79c6
D/MainActivity: onStart()
D/MainActivity: onResume()

点击按钮后,明显原来的那个活动关闭,又重新创建了一个新活动,根据内存地址可以看出:

D/MainActivity: onPause()
D/MainActivity: onCreate()com.example.det_hudie.MainActivity@3013507
D/MainActivity: onStart()
D/MainActivity: onResume()
D/MainActivity: onStop()com.example.det_hudie.MainActivity@75d79c6

SingleTop 栈顶复用模式

分两种处理情况:要创建的Activity已经处于栈顶时,此时会直接复用栈顶的Activity。不会再创建新的Activity;若须要创建的Activity不处于栈顶,此时会又一次创建一个新的Activity入栈,同Standard模式一样。
生命周期:若情况一中栈顶的Activity被直接复用时,它的onCreate、onStart不会被系统调用,由于它并没有发生改变。可是一个新的方法 onNewIntent会被回调(Activity被正常创建时不会回调此方法)。

自身调用自身不用进行新建,因为MainActivity 本身就在栈顶

// 为按钮添加事件监听器
        button1.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                //接收来自其他页面的返回值
                Intent intent=new Intent(MainActivity.this,MainActivity.class);
                startActivity(intent);
            }
        });

打印log,没有对活动进行新建
D/MainActivity: onPause()
D/MainActivity: onResume()

如果由 MainActivity - > OtherActivity -> MainActivity 则需要关闭原有的MainActivity ,然后由OtherActivity返回后 再新建 MainActivity
MainActivity :

button3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent=new Intent(MainActivity.this,ThirdActivity.class);
                startActivity(intent);
            }
        });

OtherActivity :

button4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent=new Intent(ThirdActivity.this,MainActivity.class);
                startActivity(intent);
            }
        });

结果打印log,原 MainActivity 先关闭再重建
D/MainActivity: onPause()
D/MainActivity: onStop()com.example.det_hudie.MainActivity@ceaf04b
D/MainActivity: onCreate()com.example.det_hudie.MainActivity@e285a9f
D/MainActivity: onStart()
D/MainActivity: onResume()

3 SingleTask 栈内复用模式

若要创建的Activity已经处于栈中时,此时不会创建新的Activity,而是将存在栈中的Activity上面的其他Activity所有销毁,使它成为栈顶。
生命周期:同SingleTop 模式中的情况一同样。仅仅会又一次回调Activity中的 onNewIntent 方法
举例:此时Activity 栈中以此有A、B、C三个Activity。此时C处于栈顶,启动模式为SingleTask 模式。
情况一:
在C Activity中加入点击事件,须要跳转到还有一个同类型的C Activity。结果是直接用栈顶的C Activity。
情况二:
在C Activity中加入点击事件,须要跳转到还有一个A Activity。结果是将A Activity上面的B、C所有销毁,使 A Activity成为栈顶。

将 AndroidManifest.xml 中的加载模式改为:android:launchMode=“singleTask”

<activity android:name=".MainActivity"
            android:launchMode="singleTask">
            <!--
            意图过滤器
            action:行为,为 MAIN 主行为
            category:为activity的种类 这里是 Launcher 即项目加载即执行
            -->
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

在MainActivity 中添加 onRestart 方法,因为在从其他 Activity 切换回来后,往往需要加载 onRestart 方法,相当于入栈操作。

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

在 ThirdActivity 中添加 onDestory 方法,从 ThirdActivity 切换回 MainActivity 往往需要加载 onDestory 方法。

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

则更改以上内容后,会输出以下的日志信息
1 从 MainActivity 切换到 ThirdActivity 时,会有以下日志:

D/MainActivity: onPause()
D/MainActivity: onStop()com.example.det_hudie.MainActivity@75d79c6

2 从 ThirdActivity 切换到 MainActivity 时,会有以下日志:

D/MainActivity: onRestart()
D/MainActivity: onStart()
D/MainActivity: onResume()
D/ThirdActivity: onDestory()
4 SingleInstance 单实例模式

SingleInstance比较特殊,是全局单例模式,是一种加强的SingleTask模式。它除了具有它所有特性外,还加强了一点:具有此模式的Activity仅仅能单独位于一个任务栈中。
这个经常使用于系统中的应用,比如Launch、锁屏键的应用等等,整个系统中仅仅有一个!不经常用。

将 AnroidManifest.xml 中的 SecondActivity 的加载模式替换为 SingleInstance

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

活动传递操作为: MainActivity -> SecondActivity -> ThirdActivity 则日志文件打印为:

D/MainActivity: onCreate()63
D/SecondActivity: onCreate()64
D/ThirdActivity: onCreate()63

可以发现SecondActivity 的 栈 id 和 MainActivity与ThirdActivity不同,因为他是重新生成了一个单例。
我们知道 在Android 中是任务栈的形式存储的,但是在 ThirdActivity 如果点击 返回按钮,返回的是 MainActivity 而不是 SecondActivity 因为 MainActivity与ThirdActivity在同一个任务栈中。

总结

以上是关于栈的活动模式的理解,欢迎指正, 其中有借鉴网上内容的部分.