配置Activity的時候我們可以指定android:launchMode屬性,該屬性用於配置該Activity的加載模式,支持4個屬性值:
1.standard:標準模式,系統默認的加載模式就是這個
2.singleTop:Task頂單例模式
3.singleTask:Task內單例模式
4.singleInstance:全局單例模式
Activity的加載模式的作用:android對Activity的管理是通過Task來管理多個activity的,當我們啓動一個應用時,android就會位置創建一個task,我們可以把task理解成activity棧,task以棧的形式來管理activity,先啓動的activity被放在task棧底,後面啓動的放在上面,這也就是我們所的後進先出,activity的加載模式就負責實例化,加載activity的方式,並可以控制activity與task之間的加載關係。
模式一:standard
特性:這種模式不會啓動新的task,新Activity將被添加到遠來的task中,也就是說我們通過getTaskId()拿到的id號是同一個,但是activity的對象永遠是新的一個,因此我們在task中的效果就是:
我們會發現點擊三次對象是不斷new出來的,因此activity沒有複用,而且我們想要返回,是通過點擊了4次back才返回的,這是以爲啓動的時候task中有一個,然後點擊了三次,因此必須點擊4次task才能清空!並且可以發現taskId是唯一的不變的
**
模式二:singleTop
**
這種模式的啓動與standard模式基本相似,
1.只是當將要被啓動的目標Activity已經位於Task棧頂時,系統不會重新創建目標Activity的實例
2.當將要被啓動的Activity**沒有位於Task棧頂時,系統會重新創建新的Activity**並且將它放到task棧頂,此時的特點體現於standard模式完全的相同!
實例演示:
點擊了3次button,每次的activity都是一樣的,說明我們沒new新的出來,並且taskId也是同樣的一個,測試的時候我們只需要把AndroidManifest.xml中的
lunchMode 由standard 改成 singleTop即可
<activity
android:name="com.qs.activitylifedemo.StandardTest"
android:label="@string/app_name"
android:launchMode="singleTop"
>
下面給出上面兩個例子的測試code:
public class StandardTest extends Activity {
private TextView textView;
private ClickCountUtils utils = ClickCountUtils.getInstance();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout layout = new LinearLayout(this);
this.setContentView(layout);
layout.setOrientation(LinearLayout.VERTICAL);
textView = new TextView(this);
textView.setText("當前的Activity是"+this.toString()+"\n 當前使用的taskId="+this.getTaskId()+"\n 你點擊了"+utils.getClickCount()+"次");
layout.addView(textView);
Button button = new Button(this);
button.setText("點擊跳轉到taskId爲"+getTaskId()+"的界面");
layout.addView(button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
utils.addOne();
textView.setText("當前的Activity是"+StandardTest.this.toString()+"\n 當前使用的taskId="+StandardTest.this.getTaskId()+"\n 你點擊了"+utils.getClickCount()+"次");
Intent intent = new Intent(StandardTest.this,StandardTest.class);
startActivity(intent);
}
});
}
@Override
public void onBackPressed() {
super.onBackPressed();
utils.reduceOne();
}
@Override
protected void onDestroy() {
super.onDestroy();
utils.clearClickCount();
}
}
而我們用來統計鼠標點擊次數的就是一個簡單的單例模式:
public class ClickCountUtils {
private static ClickCountUtils utils;
private static int ClickCount=0;
private ClickCountUtils(){
}
public static synchronized ClickCountUtils getInstance(){
if(utils == null){
utils = new ClickCountUtils();
}
return utils;
}
public void addOne(){
ClickCount++;
System.out.println(ClickCount);
}
public void reduceOne(){
ClickCount--;
if(ClickCount<0)ClickCount=0;
}
public int getClickCount(){
System.out.println("getClickCount="+ClickCount);
return ClickCount;
}
public void clearClickCount(){
ClickCount=0;
}
}
**
模式三:singleTask
**
採用這種加載模式的Activity 在同一個task內只有一個實例,分爲三種情況:
1.如果將要啓動的activity不存在,new一個並且添加到task棧頂
2.如果將要啓動的activity存在且已經位於棧頂了,此時與singleTop模式行爲相同
3.如果將要啓動的activity存在但是沒有位於棧頂,系統將會把它上面的所有的activity全部移除棧然後讓其位於棧頂
這個模式的過程就有點複雜了,我們先通過一個圖來了解一下怎麼操作的
這個上面第一張圖片是我們點擊了button之後跳到第二個activity之後然後在點擊跳回第一個activity的棧的效果,此時和standard模式是一樣的因爲singleTaskTest模式就是默認模式(standard),我們設置secondActivity模式爲singleTask模式,因此點擊再次點擊singleTaskTest中的button跳到secondActivity的時候我們居然發現了點擊事件被重置了,現在顯示的是1,因此我們可以大膽的估算是調用了singleTaskTest中的onDestory函數,因爲函數的寫法是:
@Override
protected void onDestroy() {
System.out.println("SingleTaskTest call onDestory()");
super.onDestroy();
utils.clearClickCount();
}
然後看我們打印的結果:
發現函數被調用了,因此得出了當secondActivity想要顯示在棧頂的時候,系統強制把位於它上面的所有的activity全部都移除棧頂了,因此我們點擊事件才被重置了!
看一下我們的點擊效果:
動畫解析:
當我們進入的時候模式是standard模式的singleTaskTest—(顯示點擊0次)—>SecondActivity_SingleTask—(顯示點擊1次)—–>singleTaskTest—–(顯示點擊兩次)—>然後在此點擊的時候出發了singleTask的特性,也就是我們上面說的情況3,我們會清除singleTaskTest,因此看到了顯示點擊了1次(由於ui刷新太快,顯示出了第一次的幀界面,暫且這樣理解,我也不知道什麼問題,知道的朋友還請多多指點一下,多謝!)然後立馬顯示點擊0次,說明我們的singleTaskTest出棧了而且我們發現當顯示點擊兩次的時候和顯示0次的時候對象不是同一個對象,一個是2d4 一個是3c8然後點擊的時候又出現了52c,這正是我們standard的特性,每次都是new一個新的activity,因此這個又在這裏得到證實,最後點擊back鍵的時候我們發現點擊了一次,直接退出SecondActivity_SingleTask,然後再點擊一次之後從singleTaskTest直接退出了app,因此這裏我們可以得出task在SecondActivity_SingleTask在棧頂的時候是兩個,你會發現最後一個出棧的永遠是我們的第一個進棧的2d4,因此在點擊2次的時候退棧需要三次,在點擊到SecondActivity_SingleTask界面的時候需要兩次,因爲清除棧頂,只剩下第一次剛進來時候的棧底和自己本身,所以問題證明完畢!
模式四:singleInstance
在這種加載模式下,系統無論從哪個Task中啓動Activity,只會創建一個Activity實例,並且會使用一個全新的棧來裝載Activity實例,啓動分如下兩種情況:
1.如果要啓動的Activity實例不存在,那麼系統會創建一個全新的Task,再創建目標實例,並將它加入到新棧中
2.如果將要啓動的目標Activity已經存在,那麼無論位於哪個應用程序中,無論它位於哪個Task中,系統會自動的把該Activity所在的Task轉到前臺,從而使該Activity顯示出來
需要指出的是,採用singleInstance模式加載Activity總是位於Task的頂部,採用這個模式加載的Task只包含這個Activity
下面看一下圖片演示:
主要觀察的是我們的兩個taskId,這兩個Activity中SecondActivity_SingleInstance 的模式是singleInstance SingleInstanceTest模式是standard,因此我們發現了SecondActivity_SingleInstance 爲68 而SingleInstanceTest 爲66 這個就是創建一個全新的Task,因此滿足了特性1,而特性二我們只需要在創建一個app然後通過intent啓動指定action的activity即可做到,這部分將在code中給出,因此不再多說!
效果顯示如圖:
我們可以發現我們從另一個app中直接跳到了我們app的SecondActivity_SingleInstance ,這裏顯示的就是我們的特性二
後話:貌似圖片顯示的很快,有點看不清楚,是因爲csdn只限制2m,因此只能少幀了,還望諒解!
代碼稍後給出,有什麼寫的不對的地方,還希望各位大神指出來,讓我多多長姿勢!