Activity的4種加載模式解析:

配置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,因此只能少幀了,還望諒解!
代碼稍後給出,有什麼寫的不對的地方,還希望各位大神指出來,讓我多多長姿勢!

Code下載地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章