Android有四种启动模式,分别是standard,singleTop,singleTask,singleInstance。下面分别简单的介绍下这四种启动模式的作用。
standard
Android 默认的一种启动模式。不需要为activity设置launchMode。这种启动模式简单的来说就是当你startActivity的时候,他就创建一个。
singleTop
这种模式模式从字面意思就能看得出来,就是当前的activity处于栈顶的时候,当你startActivity当前的activity的时候,它不会创建新的activity,而是会复用之前的activity。举个例子,startActivity了一个ActivityA,ActivityA又startActivity了ActivityB,当在ActivityB再次startActivity一个ActivityB的时候,它不会创建一个新的ActivityB,而是复用之前的ActivityB。
这里需要注意的是,只有当前的activity处于栈顶的时候才管用。举个例子:startActivity了一个ActivityA,ActivityA又startActivity了ActivityB,ActivityB又startActivity了ActivityA,那么ActivityA还是会重新创建,而不是复用之前的ActivityA。
singleTask
单一任务。意思就是说当前的activity只有一个实例,无论在任何地方startActivity出来这个activity,它都只存在一个实例。并且,它会将在他之上的所有activity都销毁。通常这个activity都是用来作为MainActivity。因为主页只需要存在一个,然后回到主页的时候可以将所有的activity都销毁起到退出应用的作用。举个例子,startActivity了一个ActivityA,ActivityA的启动模式为singleTask,那么在ActivityA里startActivity了一个ActivityB,在ActivityB里startActivity了一个ActivityC。此时在当前的任务栈中的顺序是,ActivityA->ActivityB->ActivityC。然后在ActivityC里重新startActivity了一个ActivityA,此时ActivityA会将存在于它之上的所有activity都销毁。所以此时任务栈中就只剩下ActivityA了。
singleInstance
这个模式才是重点,也是比较容易入坑的一种启动模式。字面上理解为单一实例。它具备所有singleTask的特点,唯一不同的是,它是存在于另一个任务栈中。上面的三种模式都存在于同一个任务栈中,而这种模式则是存在于另一个任务栈中。
注意事项
以往的理解中,只要在AndroidManifest.xml
中声明singleTop
或者singleInstance
,那么在使用startActivity
或者startActivityForResult
的时候,自动就会保证singleInstance
的情况下只有一个对象,singleTop
的情况下不会两个相同的Activity
叠加在一起。
但是现实是让人崩溃的。
使用如下的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
package com.mobibrw.myapplication; import androidx.appcompat.app.AppCompatActivity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; public class MainActivity extends AppCompatActivity { private final static int SINGLE_INSTANCE = 1; private final static int SINGLE_TOP = 2; private void startSingleInstanceActivity() { final Intent intent = new Intent(this, SingleInstanceActivity.class); //intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); startActivityForResult(intent, SINGLE_INSTANCE); } private void startSingleTopActivity() { final Intent intent = new Intent(this, SingleTopActivity.class); //intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); startActivityForResult(intent, SINGLE_TOP); } private void startSingleInstanceWithFlagsActivity() { final Intent intent = new Intent(this, SingleInstanceActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); startActivityForResult(intent, SINGLE_INSTANCE); } private void startSingleTopWithFlagsActivity() { final Intent intent = new Intent(this, SingleTopActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); startActivityForResult(intent, SINGLE_TOP); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btnSingleTop = findViewById(R.id.SingleTop); btnSingleTop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { startSingleTopActivity(); startSingleTopActivity(); } }); Button btnSingleInstance = findViewById(R.id.SingleInstance); btnSingleInstance.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { startSingleInstanceActivity(); startSingleInstanceActivity(); } }); Button btnSingleTopWithFlags = findViewById(R.id.SingleTopWithFlags); btnSingleTopWithFlags.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { startSingleTopWithFlagsActivity(); startSingleTopWithFlagsActivity(); } }); Button btnSingleInstanceWithFlags = findViewById(R.id.SingleInstanceWithFlags); btnSingleInstanceWithFlags.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { startSingleInstanceWithFlagsActivity(); startSingleInstanceWithFlagsActivity(); } }); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.mobibrw.myapplication"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".SingleInstanceActivity" android:launchMode="singleInstance"/> <activity android:name=".SingleTopActivity" android:launchMode="singleTop"/> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> |
在两次触发startSingleTopActivity
/startSingleInstanceActivity
的时候,出现了两个叠加的Activity
,如下:
1 2 3 4 5 6 7 8 |
$ adb shell dumpsys activity | grep SingleTopActivity Hist #2: ActivityRecord{6f4fc4 u0 com.mobibrw.myapplication/.SingleTopActivity t457} Intent { cmp=com.mobibrw.myapplication/.SingleTopActivity } Hist #1: ActivityRecord{4a4ec71 u0 com.mobibrw.myapplication/.SingleTopActivity t457} Intent { cmp=com.mobibrw.myapplication/.SingleTopActivity } Run #1: ActivityRecord{6f4fc4 u0 com.mobibrw.myapplication/.SingleTopActivity t457} mResumedActivity: ActivityRecord{6f4fc4 u0 com.mobibrw.myapplication/.SingleTopActivity t457} mFocusedActivity: ActivityRecord{6f4fc4 u0 com.mobibrw.myapplication/.SingleTopActivity t457} |
可以看到出现两个单独的实例 Hist #2/Hist #1,而不是预期的忽略第二次调用。
在两次触发startSingleTopWithFlagsActivity
/startSingleInstanceWithFlagsActivity
的时候,只会出现了一个Activity
,如下:
1 2 3 4 5 6 |
$ adb shell dumpsys activity | grep SingleTopActivity Hist #1: ActivityRecord{933a335 u0 com.mobibrw.myapplication/.SingleTopActivity t457} Intent { flg=0x420000 cmp=com.mobibrw.myapplication/.SingleTopActivity } Run #1: ActivityRecord{933a335 u0 com.mobibrw.myapplication/.SingleTopActivity t457} mResumedActivity: ActivityRecord{933a335 u0 com.mobibrw.myapplication/.SingleTopActivity t457} mFocusedActivity: ActivityRecord{933a335 u0 com.mobibrw.myapplication/.SingleTopActivity t457} |
两者的区别就是
1 |
intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); |
这句代码。
还是学艺不精啊。
完整例子代码,点击此处下载 MyApplication