1. 程式人生 > >Android關於Task的一些實踐之SingleTask, SingleInstance和TaskAffinity

Android關於Task的一些實踐之SingleTask, SingleInstance和TaskAffinity

conda tag 我們 創建 真理 enter 設置 com lms

上一篇文章粗略地介紹了一下關於Android中Task的基本知識。只是實踐才是檢驗真理的唯一標準,所以。今天就來試驗一下Task中的launchMode是否真的實現了文檔所說的那樣。

首先。定義三個Activity。MainActivity打開SecondActivity,SecondActivity打開ThirdActivity,例如以下所看到的:

技術分享

技術分享

技術分享

以下。我們定義Second Activity的Launch Mode。分別有以下幾種情況:

1)Standard(即不定義)

首先是默認情況下。什麽都不定義。例如以下:

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.lms.taskdemo.MainActivity"
            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="com.lms.taskdemo.SecondActivity">
        </activity>
        <activity android:name="com.lms.taskdemo.ThirdActivity" >
        </activity>
    </application>
順序打開三個Activity,看看結果:

04-21 15:23:28.373: V/com.lms.taskdemo(20473): Task : 70
04-21 15:23:28.373: V/com.lms.taskdemo(20473): Base activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.MainActivity}
04-21 15:23:28.373: V/com.lms.taskdemo(20473): Current activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.MainActivity}
04-21 15:23:28.373: V/com.lms.taskdemo(20473): Number of activities : 1
04-21 15:23:28.373: V/com.lms.taskdemo(20473): Number of running activities: 1
04-21 15:23:31.336: V/com.lms.taskdemo(20473): Task : 70
04-21 15:23:31.336: V/com.lms.taskdemo(20473): Base activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.MainActivity}
04-21 15:23:31.336: V/com.lms.taskdemo(20473): Current activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.SecondActivity}
04-21 15:23:31.336: V/com.lms.taskdemo(20473): Number of activities : 2
04-21 15:23:31.336: V/com.lms.taskdemo(20473): Number of running activities: 2
04-21 15:23:33.999: V/com.lms.taskdemo(20473): Task : 70
04-21 15:23:33.999: V/com.lms.taskdemo(20473): Base activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.MainActivity}
04-21 15:23:33.999: V/com.lms.taskdemo(20473): Current activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.ThirdActivity}
04-21 15:23:33.999: V/com.lms.taskdemo(20473): Number of activities : 3
04-21 15:23:33.999: V/com.lms.taskdemo(20473): Number of running activities: 3

能夠看到三個Activity,都是在同個Task中的。

2)SingleTask

為Second Activity,定義其launch mode 為 “singleTask”。例如以下:

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.lms.taskdemo.MainActivity"
            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="com.lms.taskdemo.SecondActivity"
            android:launchMode="singleTask">
        </activity>
        <activity android:name="com.lms.taskdemo.ThirdActivity" >
        </activity>
    </application>

再來看看其結果,例如以下:

04-22 10:31:26.197: V/com.lms.taskdemo(924): Task : 162
04-22 10:31:26.217: V/com.lms.taskdemo(924): Base activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.MainActivity}
04-22 10:31:26.217: V/com.lms.taskdemo(924): Current activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.MainActivity}
04-22 10:31:26.217: V/com.lms.taskdemo(924): Number of activities : 1
04-22 10:31:26.217: V/com.lms.taskdemo(924): Number of running activities: 1
04-22 10:31:31.112: V/com.lms.taskdemo(924): Task : 162
04-22 10:31:31.112: V/com.lms.taskdemo(924): Base activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.MainActivity}
04-22 10:31:31.112: V/com.lms.taskdemo(924): Current activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.SecondActivity}
04-22 10:31:31.112: V/com.lms.taskdemo(924): Number of activities : 2
04-22 10:31:31.112: V/com.lms.taskdemo(924): Number of running activities: 2
04-22 10:31:32.884: V/com.lms.taskdemo(924): Task : 162
04-22 10:31:32.884: V/com.lms.taskdemo(924): Base activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.MainActivity}
04-22 10:31:32.884: V/com.lms.taskdemo(924): Current activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.ThirdActivity}
04-22 10:31:32.884: V/com.lms.taskdemo(924): Number of activities : 3
04-22 10:31:32.884: V/com.lms.taskdemo(924): Number of running activities: 2

發現盡管定義了SingleTask,但Second Activity和Main Activity還是在同一個Task中。這跟我們期望的不符。原因事實上在於,設置了launchMode = SingleTask啟動的Activity,在啟動的時候,會去查找跟它的taskAffinity同樣的task,假設存在這樣一個task,就在這個task中啟動,假設不存在這樣一個task,才創建一個新的task,並在新task中啟動。

而在這裏,由於沒有為各個activity定義taskAffinity,那麽默認的affinity值就是包名,那麽幾個Activity都是一樣的,所以就在相同的Task中啟動了。

3)Single Task Different Task Affinity

以下。我們分別為Main Activity和 Second Activity設置不同的TaskAffinity值,例如以下:

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.lms.taskdemo.MainActivity"
            android:label="@string/app_name"
            android:taskAffinity="com.lms.taskdemo.MainActivity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.lms.taskdemo.SecondActivity"
            android:launchMode="singleTask"
            android:taskAffinity="com.lms.taskdemo.SecondActivity" >
        </activity>
        <activity android:name="com.lms.taskdemo.ThirdActivity" >
        </activity>
    </application>

以下是結果,啟動的順序是Main Activity->Second Activity->Main Activity -> Second Activity -> Third Activity

04-22 10:26:27.818: V/com.lms.taskdemo(32677): Task : 151
04-22 10:26:27.818: V/com.lms.taskdemo(32677): Base activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.MainActivity}
04-22 10:26:27.818: V/com.lms.taskdemo(32677): Current activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.MainActivity}
04-22 10:26:27.818: V/com.lms.taskdemo(32677): Number of activities : 1
04-22 10:26:27.818: V/com.lms.taskdemo(32677): Number of running activities: 1
04-22 10:26:31.362: V/com.lms.taskdemo(32677): Task : 152
04-22 10:26:31.362: V/com.lms.taskdemo(32677): Base activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.SecondActivity}
04-22 10:26:31.362: V/com.lms.taskdemo(32677): Current activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.SecondActivity}
04-22 10:26:31.372: V/com.lms.taskdemo(32677): Number of activities : 1
04-22 10:26:31.372: V/com.lms.taskdemo(32677): Number of running activities: 1
04-22 10:26:36.558: V/com.lms.taskdemo(32677): Task : 151
04-22 10:26:36.558: V/com.lms.taskdemo(32677): Base activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.MainActivity}
04-22 10:26:36.558: V/com.lms.taskdemo(32677): Current activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.MainActivity}
04-22 10:26:36.558: V/com.lms.taskdemo(32677): Number of activities : 1
04-22 10:26:36.558: V/com.lms.taskdemo(32677): Number of running activities: 1
04-22 10:26:39.401: V/com.lms.taskdemo(32677): Task : 153
04-22 10:26:39.401: V/com.lms.taskdemo(32677): Base activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.SecondActivity}
04-22 10:26:39.401: V/com.lms.taskdemo(32677): Current activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.SecondActivity}
04-22 10:26:39.401: V/com.lms.taskdemo(32677): Number of activities : 1
04-22 10:26:39.401: V/com.lms.taskdemo(32677): Number of running activities: 1
04-22 10:26:41.123: V/com.lms.taskdemo(32677): Task : 153
04-22 10:26:41.123: V/com.lms.taskdemo(32677): Base activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.SecondActivity}
04-22 10:26:41.123: V/com.lms.taskdemo(32677): Current activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.ThirdActivity}
04-22 10:26:41.123: V/com.lms.taskdemo(32677): Number of activities : 2
04-22 10:26:41.123: V/com.lms.taskdemo(32677): Number of running activities: 2

在上面的結果中,能夠看到在啟動Second Activity的時候,的確是在一個新的Task中啟動了。Second Activity是這個Task中的根Activity。而由Second Activity啟動的Third Activity也是在這個Task中啟動的。

4)Single Instance

以下,我們再來看看Single Instance,相同的,先不定義Task Affinity。在AndroidManifest文件裏定義例如以下:
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.lms.taskdemo.MainActivity"
            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="com.lms.taskdemo.SecondActivity"
            android:launchMode="singleInstance">
        </activity>
        <activity android:name="com.lms.taskdemo.ThirdActivity" >
        </activity>
    </application>

以下是結果:
04-22 10:29:43.207: V/com.lms.taskdemo(682): Task : 159
04-22 10:29:43.207: V/com.lms.taskdemo(682): Base activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.MainActivity}
04-22 10:29:43.207: V/com.lms.taskdemo(682): Current activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.MainActivity}
04-22 10:29:43.207: V/com.lms.taskdemo(682): Number of activities : 1
04-22 10:29:43.207: V/com.lms.taskdemo(682): Number of running activities: 1
04-22 10:29:46.580: V/com.lms.taskdemo(682): Task : 160
04-22 10:29:46.580: V/com.lms.taskdemo(682): Base activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.SecondActivity}
04-22 10:29:46.580: V/com.lms.taskdemo(682): Current activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.SecondActivity}
04-22 10:29:46.580: V/com.lms.taskdemo(682): Number of activities : 1
04-22 10:29:46.580: V/com.lms.taskdemo(682): Number of running activities: 1
04-22 10:29:48.202: V/com.lms.taskdemo(682): Task : 159
04-22 10:29:48.202: V/com.lms.taskdemo(682): Base activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.MainActivity}
04-22 10:29:48.202: V/com.lms.taskdemo(682): Current activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.ThirdActivity}
04-22 10:29:48.202: V/com.lms.taskdemo(682): Number of activities : 2
04-22 10:29:48.202: V/com.lms.taskdemo(682): Number of running activities: 1
04-22 10:29:57.112: V/com.lms.taskdemo(682): Task : 160
04-22 10:29:57.112: V/com.lms.taskdemo(682): Base activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.SecondActivity}
04-22 10:29:57.112: V/com.lms.taskdemo(682): Current activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.SecondActivity}
04-22 10:29:57.112: V/com.lms.taskdemo(682): Number of activities : 1
04-22 10:29:57.112: V/com.lms.taskdemo(682): Number of running activities: 1
能夠看到啟動Second Activity的時候,是在新的Task中,而當啟動Third Activity的時候,它又跑回原來的Task中去了。這是跟文檔描寫敘述中符合的。的確是新建的Task中僅僅能有且僅有一個Activity。

而因為我們未定義Task Affinity,所以當啟動Third Activity的時候。它就會去找同樣Affinity的task,所以就會找到原來的Task。也即是說,假設定義了TaskAffinity的話,那以Third Activity就應該在新的Task中創建了,以下就來驗證一下。


5)Single Instance Different Affinity

在配置文件裏定義例如以下:
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.lms.taskdemo.MainActivity"
            android:label="@string/app_name"
            android:taskAffinity="com.lms.taskdemo.MainActivity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.lms.taskdemo.SecondActivity"
            android:launchMode="singleInstance"
            android:taskAffinity="com.lms.taskdemo.SecondActivity" >
        </activity>
        <activity android:name="com.lms.taskdemo.ThirdActivity" >
        </activity>
    </application>

以下來看看結果,例如以下:
04-22 10:27:58.866: V/com.lms.taskdemo(391): Task : 155
04-22 10:27:58.866: V/com.lms.taskdemo(391): Base activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.MainActivity}
04-22 10:27:58.866: V/com.lms.taskdemo(391): Current activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.MainActivity}
04-22 10:27:58.866: V/com.lms.taskdemo(391): Number of activities : 1
04-22 10:27:58.866: V/com.lms.taskdemo(391): Number of running activities: 1
04-22 10:28:00.677: V/com.lms.taskdemo(391): Task : 156
04-22 10:28:00.677: V/com.lms.taskdemo(391): Base activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.SecondActivity}
04-22 10:28:00.677: V/com.lms.taskdemo(391): Current activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.SecondActivity}
04-22 10:28:00.677: V/com.lms.taskdemo(391): Number of activities : 1
04-22 10:28:00.677: V/com.lms.taskdemo(391): Number of running activities: 1
04-22 10:28:02.309: V/com.lms.taskdemo(391): Task : 157
04-22 10:28:02.309: V/com.lms.taskdemo(391): Base activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.ThirdActivity}
04-22 10:28:02.309: V/com.lms.taskdemo(391): Current activity : ComponentInfo{com.lms.taskdemo/com.lms.taskdemo.ThirdActivity}
04-22 10:28:02.309: V/com.lms.taskdemo(391): Number of activities : 1
04-22 10:28:02.309: V/com.lms.taskdemo(391): Number of running activities: 1

果然。如我們期望的那樣,都是在一個新的Task中啟動當前的Activity的。


總結:

當使用Launch Mode 來改變系統默認的任務調度的時候。假設是用到Single Task或者Single Instance的時候,還要註意到Affinity的使用,要跟Affinity配合使用。可能才幹達到我們期望中的效果。而Affinity,事實上是Android提供的一個表從屬意義的參數,類似於一個Tag值,它表明當前Activity屬於哪一個Tag,相當的Affinity值的Activity。假設不使用其它的標誌,如Single Instance之類,那麽都會在存在於同一個task中。普通情況下,我們並不定義Task Affinity值。則其默認的值就是當前App的包名。
結束。

Android關於Task的一些實踐之SingleTask, SingleInstance和TaskAffinity