standard:標準模式
android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag.
public class FirstActivity
extends AppCompatActivity
{
private static final String TAG = "FirstActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
String test = savedInstanceState.getString("extra_test");
Log.e(TAG, "[onCreate] restore extra_test:" + test);
}
TextView textView = findViewById(R.id.tast_id1);
textView.setText(this.toString() + "\n" + "current task id: " + this.getTaskId());
findViewById(R.id.first_btn2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(getApplicationContext(), SecondActivity.class));
}
});
findViewById(R.id.first_btn1).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(getApplicationContext(), FirstActivity.class));
}
});
}
}
singleTop:棧頂複用模式,解決重複創建棧頂活動的問題。
我們看到這個結果跟standard有所不同,2個序列號是相同的,也就是說使用的都是同一個FirstActivity實例;如果按一下後退鍵,程序立即退出,說明當前棧結構中只有一個Activity實例。singleTop模式的原理如下圖所示:
public class SecondActivity
extends AppCompatActivity
{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
TextView textView = findViewById(R.id.tast_id2);
textView.setText(this.toString() + "\n" + "current task id: " + this.getTaskId());
findViewById(R.id.second_btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(SecondActivity.this, FirstActivity.class));
}
});
findViewById(R.id.second_btn2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(SecondActivity.this, SecondActivity.class));
}
});
}
}
然後將之前的FirstActivity跳轉代碼改爲:
startActivity(new Intent(getApplicationContext(), SecondActivity.class));
FirstActivity會跳轉到SecondActivity,SecondActivity又會跳轉到FirstActivity。演示結果如下:
我們看到,兩個FirstActivity的序列號是不同的,證明從SecondActivity跳轉到FirstActivity時生成了新的FirstActivity實例。原理圖如下:
我們看到,兩個FirstActivity的序列號是不同的,證明從SecondActivity跳轉到FirstActivity時生成了新的FirstActivity實例。原理圖如下:
singleTask:棧內複用模式,讓某個活動在整個應用程序的上下文中只存在一個實例。
我們注意到,在上面的過程中,FirstActivity的序列號是不變的,SecondActivity的序列號卻不是唯一的,說明從SecondActivity跳轉到FirstActivity時,沒有生成新的實例,但是從FirstActivity跳轉到SecondActivity時生成了新的實例。singleTask模式的原理圖如下圖所示:
singleInstance:單實例模式,共享活動實例的問題。
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.example.yhadmin.activitydemo2"
xmlns:android="http://schemas.android.com/apk/res/android">
<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=".FirstActivity"
android:launchMode="standard">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".SecondActivity"
android:launchMode="singleInstance">
</activity>
</application>
</manifest>
我們在每個Activity中顯示當前棧結構的id,每個Activity添加如下代碼:
TextView textView = findViewById(R.id.tast_id1);
textView.setText(this.toString() + "\n" + "current task id: " + this.getTaskId());
然後我們再演示一下這個流程:
我們發現這兩個Activity實例分別被放置在不同的棧結構中,關於singleInstance的原理圖如下: