在多Activity開發中,有可能是自己應用之間的Activity跳轉,也有可能夾帶其他應用的可複用的Activity,可能會希望跳轉到原來某個Activity實例,而不產生大量重複的Activity。這需要爲Activity配置特定的加載模式,而不是使用默認的加載模式。
Activity有四種加載模式,分別爲:
1、standard:標準模式(默認模式),一調用startActivity()方法就會產生一個新的實例。
2、singleTop:如果Activity實例位於棧頂,就不產生新的實例,直接使用棧頂的實例,否則,就會產生一個新的實例。
例如:現在Task棧元素爲A-B-C-D(D在棧頂),這時候給D發一個啓動Intent,如果D是 “standard”模式的,則生成D的一個新實例,棧狀態爲A-B-C-D-D。如果D是singleTop模式的話,則不會生成D的新實例,棧狀態仍爲A-B-C-D。如果這時候給B發Intent的話,不管B的launchMode是“standard”還是“singleTop”,都會生成B的新實例,棧狀態變爲A-B-C-D-B。
3、singleTask:每次調用都會使用這個實例,不會去產生新的實例了。
4、singleInstance:跟singleTask模式基本上是一樣,只有一個區別:在這個模式下的Activity實例與其他Activity處在不同的Task中,此實例所處的Task中只能有這個Activity實例,不能有其他的實例。
如何設置Activity的加載模式?
加載模式可以在清單文件AndroidManifest.xml中的<activity>的launchMode屬性進行配置。
<activity
android:name="ActivityOne"
android:label="@string/app_name"
android:launchMode="standard">
</activity>
四種加載模式的區別(示例說明):
1、standard模式,標準模式,也就是默認模式,不需要在launchMode屬性配置。
/**
* 默認(standard)加載模式
*
* @author Harvey
*/
public class ActivityOne extends Activity implements OnClickListener
{
private TextView textView;// 顯示文本
private Button button;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
textView = (TextView) findViewById(R.id.textView);
button = (Button) findViewById(R.id.button);
button.setText("go to ActivityOne");
button.setOnClickListener(this);
textView.setText(this + "");
}
@Override
public void onClick(View v)
{
Intent intent = new Intent();
intent.setClass(ActivityOne.this, ActivityOne.class);// 跳轉
startActivity(intent);
}
}
清單文件如下:
<activity android:name="ActivityOne"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
經過多次點擊按鈕後,發現每次在界面上顯示hash code值都不同,證明每次點擊按鈕都創建了該Activity的新實例。接着點擊返回鍵,可以看到是按照剛纔創建Activity實例的倒序依次出現,類似退棧的操作,而剛纔操作跳轉按鈕的過程是壓棧的操作。
2、singleTop模式,singleTop和standard模式都會將Intent發送新的實例(而後兩種模式如果已經有了實例,就不會發送到新的實例)。不過,singleTop要求如果創建Intent的時候棧頂已經有要創建的Activity的實例,則將Intent發送給該實例,而不發送給新的實例。
/**
* singleTop模式
*
* @author Harvey
*/
public class ActivityOne extends Activity implements OnClickListener
{
private TextView textView;// 顯示文本
private Button button;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
textView = (TextView) findViewById(R.id.textView);
button = (Button) findViewById(R.id.button);
button.setText("go to ActivityOne");
button.setOnClickListener(this);
textView.setText(this + "");
}
@Override
public void onClick(View v)
{
Intent intent = new Intent();
intent.setClass(ActivityOne.this, ActivityOne.class);// 跳轉
startActivity(intent);
}
}
清單文件如下:
<activity
android:name="ActivityOne"
android:label="@string/app_name"
android:launchMode="singleTop">
<intent-filter>
<action
android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
點擊Button按鈕數次後,發現都是相同的Activity實例,因爲該實例在棧頂,所有不會創建新的實例。如果點擊返回鍵,將退出應用。singleTop模式,可用來解決棧頂多個重複相同的Activity的問題。
如果A-Activity跳轉到B-Activity,再跳轉到A-Activity,就和standard模式一樣了,在B-Activity跳轉到A-Activity的時候就會創建A-Activity的新實例,因爲當時的棧頂不是A-Activity實例。
ActivityOne.java
/**
* singleTop模式
*
* @author Harvey
*/
public class ActivityOne extends Activity implements OnClickListener
{
private TextView textView;// 顯示文本
private Button button;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
textView = (TextView) findViewById(R.id.textView);
button = (Button) findViewById(R.id.button);
button.setText("go to ActivityTwo");
button.setOnClickListener(this);
textView.setText(this + "");
}
@Override
public void onClick(View v)
{
Intent intent = new Intent();
intent.setClass(ActivityOne.this, ActivityTwo.class);// 跳轉
startActivity(intent);
}
}
ActivityTwo.java
public class ActivityTwo extends Activity implements OnClickListener
{
private TextView textView;//顯示文本
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
textView = (TextView) findViewById(R.id.textView);
button = (Button) findViewById(R.id.button);
button.setText("go to ActivityOne");
button.setOnClickListener(this);
textView.setText(this + "");
}
@Override
public void onClick(View v)
{
Intent intent = new Intent();
intent.setClass(ActivityTwo.this, ActivityOne.class);//跳轉
startActivity(intent);
}
}
清單文件如下:
<activity
android:name="ActivityOne"
android:label="@string/app_name"
android:launchMode="singleTop">
<intent-filter>
<action
android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="ActivityTwo"
android:label="@string/app_name">
</activity>
ActivityOne使用singleTop加載模式,ActivityTwo使用默認(standard)加載模式。ActivityOne也是要生成新的實例的,如果把ActivityOne的加載模式改爲standard加載模式,結果也是一樣。
3、singleTask模式,和後面的singleInstance模式都是隻創建一個實例的。
當Intent到來,需要創建singleTask模式Activity的時候,系統會檢查棧裏面是否已經有該Activity的實例,如果有直接將Intent發送給它。
把上面singleTop的實例中的ActivityOne的launchMode改爲singleTask,ActivityTwo不改動。
<activity
android:name="ActivityOne"
android:label="@string/app_name"
android:launchMode="singleTask">
<intent-filter>
<action
android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="ActivityTwo"
android:label="@string/app_name">
</activity>
多次跳轉之後,發現Task中始終只有一個ActivityOne實例。
4、singleInstance模式
將ActivityOne的模式配置爲standard模式,將ActivityTwo的模式配置爲singleInstance模式。
ActivityOne.java
/**
* singleInstance模式
*
* @author Harvey
*/
public class ActivityOne extends Activity implements OnClickListener
{
private TextView textView;// 顯示文本
private Button button;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
textView = (TextView) findViewById(R.id.textView);
button = (Button) findViewById(R.id.button);
button.setText("go to ActivityTwo");
button.setOnClickListener(this);
textView.setText(this + "\n" + "task id:" + this.getTaskId());
}
@Override
public void onClick(View v)
{
Intent intent = new Intent();
intent.setClass(ActivityOne.this, ActivityTwo.class);// 跳轉
startActivity(intent);
}
}
ActivityTwo.java
public class ActivityTwo extends Activity implements OnClickListener
{
private TextView textView;// 顯示文本
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
textView = (TextView) findViewById(R.id.textView);
button = (Button) findViewById(R.id.button);
button.setText("go to ActivityOne");
button.setOnClickListener(this);
textView.setText(this + "\n" + "task id:" + this.getTaskId());
}
@Override
public void onClick(View v)
{
Intent intent = new Intent();
intent.setClass(ActivityTwo.this, ActivityOne.class);// 跳轉
startActivity(intent);
}
}
清單文件如下:
<activity
android:name="ActivityOne"
android:label="@string/app_name">
<intent-filter>
<action
android:name="android.intent.action.MAIN" />
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="ActivityTwo"
android:label="@string/app_name"
android:launchMode="singleInstance">
</activity>
經過多次的跳轉發現ActivityOne和ActivityTwo的task id不相同,表明兩個的Acitity不在同一個Task中。ActivityOne的hash code值在每次跳轉之後都不同,表明每次跳轉後都會創建一個新的ActivityOne實例,ActivityTwo的hash code值每次跳轉之後都相同,表明ActivityTwo所在的Task中只有一個ActivityTwo實例。