android Activity launch mode 一個執行個體 singleInstance

來源:互聯網
上載者:User

標籤:

參考:http://blog.csdn.net/zhangjg_blog/article/details/10923643#

singleInstance的特點可以歸結為以下三條:
  1. 以singleInstance模式啟動的Activity具有全域唯一性,即整個系統中只會存在一個這樣的執行個體
  2. 以singleInstance模式啟動的Activity具有獨佔性,即它會獨自佔用一個任務,被他開啟的任何activity都會運行在其他任務中(官方文檔上的描述為,singleInstance模式的Activity不允許其他Activity和它共存在一個任務中)
  3. 被singleInstance模式的Activity開啟的其他activity,能夠開啟一個新任務,但不一定開啟新的任務,也可能在已有的一個任務中開啟
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.jg.zhang.androidtasktest"    android:versionCode="1"    android:versionName="1.0" >    <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="17" />    <application android:allowBackup="true"        android:icon="@drawable/ic_launcher" android:label="androidtasktest">                <activity  android:name="com.jg.zhang.androidtasktest.MainActivity">            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>                 <activity android:name="com.jg.zhang.androidtasktest.SecondActivity"             android:launchMode="singleInstance">             <intent-filter>                 <action android:name="com.jg.zhang.androidtasktest.ACTION_MY"/>                 <category android:name="android.intent.category.DEFAULT"/>             </intent-filter>         </activity>                 <activity android:name="com.jg.zhang.androidtasktest.ThirdActivity"/>             </application>    </manifest>

  

由上面的資訊清單檔可以知道,該應用程式套件括三個activity,分別為MianActivity,SecondActivity,ThirdActivity,其中SecondActivity啟動模式設定為singleInstance。MianActivity可以開啟SecondActivity,SecondActivity可以開啟ThirdActivity。 並且為了可以在其他應用中開啟SecondActivity,為SecondActivity設定了一個IntentFilter,這樣就可以在其他應用中使用隱式Intent開啟SecondActivity。

 

為了更好的驗證singleInstance的全域唯一性,還需要其他一個應用,對上面的AndroidTaskTest1進行一些修改即可。AndroidTaskTest1隻需要一個MianActivity,在MainActivity中點擊按鈕會開啟AndroidTaskTest應用中的SecondActivity。開啟AndroidTaskTest應用中的SecondActivity的代碼如下

/** * 該方法在布局中按鈕的android:onClick屬性中指定 * android:onClick="launchOtherActivity" * @param v */public void launchOtherActivity(View v){Intent intent = new Intent();//以下Action為"com.jg.zhang.androidtasktest.ACTION_MY"//即AndroidTaskTest應用中SecondActivity的actionintent.setAction("com.jg.zhang.androidtasktest.ACTION_MY");startActivity(intent);}

執行如下操作:安裝AndroidTaskTest應用,點擊MainActivity中的按鈕,開啟SecondActivity,可以看到如下log輸出:  

執行adb shell dumpsys activity命令,有以下輸出:
TaskRecord{411189e0 #9 A com.jg.zhang.androidtasktest}
Run #2: ActivityRecord{4129af80 com.jg.zhang.androidtasktest/.SecondActivity}
TaskRecord{41305528 #8 A com.jg.zhang.androidtasktest}
Run #1: ActivityRecord{41296e60 com.jg.zhang.androidtasktest/.MainActivity}
以上可以說明,singleInstance模式的Activity總是會在新的任務中運行(前提是系統中還不存在這樣的一個執行個體) 。

 

下面驗證它的全域唯一性,執行以下操作:安裝另一個應用AndroidTaskTest1,在開啟的MainActivity中點擊按鈕開啟AndroidTaskTest應用中的SecondActivity。看到列印出一條新的日誌:

執行adb shell dumpsys activity命令,有以下輸出:

TaskRecord{411189e0 #9 A com.jg.zhang.androidtasktest}

Run #3: ActivityRecord{4129af80 com.jg.zhang.androidtasktest/.SecondActivity}

TaskRecord{412dc788 #12 A com.jg.zhang.androidtasktest1}

Run #2: ActivityRecord{4121c628 com.jg.zhang.androidtasktest1/.MainActivity}

TaskRecord{41305528 #8 A com.jg.zhang.androidtasktest}

Run #1: ActivityRecord{41296e60 com.jg.zhang.androidtasktest/.MainActivity}

 

由紅色字型可以得知,開啟的SecondActivity就是上次建立的編號為4129af80的SecondActivity,並且Log中沒有再次輸出關於SecondActivity的資訊,說明SecondActivity並沒有重新建立。由此可以得出結論:以singleInstance模式啟動的Activity在整個系統中是單例的,如果在啟動這樣的Activity時,已經存在了一個執行個體,那麼會把它所在的任務調度到前台,重用這個執行個體。

 

下面開始驗證第二個特點:以singleInstance模式啟動的Activity具有獨佔性,即它會獨自佔用一個任務,被他開啟的任何activity都會運行在其他任務中 重新安裝AndroidTaskTest應用,點擊MainActivity中的按鈕,開啟SecondActivity,在SecondActivity中點擊按鈕,開啟ThirdActivity。可以看到有如下Log輸出: 。。。  SecondActivity所在的任務為16,被SecondActivity啟動的ThirdActivity所在的任務為15,這就說明 以singleInstance模式啟動的Activity具有獨佔性,即它會獨自佔用一個任務,被他開啟的任何activity都會運行在其他任務中 下面開始驗證第三個特點:被singleInstance模式的Activity開啟的其他activity,能夠在新的任務中啟動,但不一定開啟新的任務,也可能在已有的一個任務中開啟 有上面對第二個特點的驗證可以看到,被SecondActivity啟動的ThirdActivity並沒有運行在一個新開啟的任務中,而是和MainActivity運行在了同一個已有的任務中,那麼在什麼情況下ThirdActivity才會啟動一個新的任務呢? 現在對程式的資訊清單檔做以下修改,為ThirdActivity增加一個屬性taskAffinity:

 

         <activity android:name="com.jg.zhang.androidtasktest.ThirdActivity"             android:taskAffinity="com.jg.zhang.androidtasktest.second"/>

  

重新安裝AndroidTaskTest應用,執行和上一步中同樣的操作:點擊MainActivity中的按鈕,開啟SecondActivity,在SecondActivity中點擊按鈕,開啟ThirdActivity。可以看到有如下輸出:  

執行adb shell dumpsys activity命令,有以下輸出:

TaskRecord{413551b0 #20 A com.jg.zhang.androidtasktest.second}
Run #3: ActivityRecord{412de9c0 com.jg.zhang.androidtasktest/.ThirdActivity}
TaskRecord{4134b268 #19 A com.jg.zhang.androidtasktest}
Run #2: ActivityRecord{412a36a0 com.jg.zhang.androidtasktest/.SecondActivity}
TaskRecord{413131e8 #18 A com.jg.zhang.androidtasktest}
Run #1: ActivityRecord{41271e10 com.jg.zhang.androidtasktest/.MainActivity}

 可見,被SecondActivity啟動的ThirdActivity啟動在了一個新的任務中,即在啟動ThirdActivity時建立了一個新任務。這就說明被singleInstance模式的Activity A在開啟另一activity B時,能夠開啟一個新任務,但是是不是真的開啟新任務,還要受其他條件的限制,這個條件是:當前系統中是不是已經有了一個activity B的taskAffinity屬性指定的任務。 其實這種行為和singleTask啟動時的情況相同。在Activity的啟動模式設定為singleTask時,啟動時系統會為它加上FLAG_ACTIVITY_NEW_TASK標誌,而被singleInstance模式的Activity開啟的activity,啟動時系統也會為它加上FLAG_ACTIVITY_NEW_TASK標誌,所以他們啟動時的情況是相同的,上面再驗證singleTask時已經闡述過,現在重新說明一下: 

由於ThirdActivity是被啟動模式為singleInstance類型的Activity(即SecondActivity)啟動的,framework會為它它加上FLAG_ACTIVITY_NEW_TASK標誌,這時  framework會檢索是否已經存在了一個affinity為com.jg.zhang.androidtasktest.second(即ThirdActivity的taskAffinity屬性)的任務,

 

  • 如果存在這樣的一個任務,則檢查在這個任務中是否已經有了一個ThirdActivity的執行個體,
  1. 如果已經存在一個ThirdActivity的執行個體,則會重用這個任務和任務中的ThirdActivity執行個體,將這個任務調到前台,清除位於ThirdActivity上面的所有Activity,顯示ThirdActivity,並調用ThirdActivity的onNewIntent()。
  2. 如果不存在一個ThirdActivity的執行個體,會在這個任務中建立ThirdActivity的執行個體,並調用onCreate()方法
  • 如果不存在這樣的一個任務,會建立一個新的affinity為com.jg.zhang.androidtasktest.second的任務,並且將ThirdActivity啟動到這個新的任務中

 

 

如果ThirdActivity不設定taskAffinity,即ThirdActivity和MainActivity的taskAffinity相同,都為應用的包名,那麼ThirdActivity是不會開啟一個新任務的,framework中的判定過程如下:

 

  1. 在SecondActivity啟動ThirdActivity時,因為SecondActivity是singleInstance的,所以設定ThirdActivity的啟動標誌為FLAG_ACTIVITY_NEW_TASK
  2. 然後獲得ThirdActivity的taskAffinity,即為包名com.jg.zhang.androidtasktest
  3. 檢查是否已經存在一個affinity為com.jg.zhang.androidtasktest的任務,這個任務是存在的,就是MainActivity所在的任務,這個任務是在啟動MainActivity時開啟的
  4.  既然已經存在這個任務,就檢索在這個任務中是否存在一個ThirdActivity的執行個體,發現不存在
  5.  在這個已有的任務中啟動一個SecondActivity的執行個體

 

為了作一個清楚的比較,列出ThirdActivity的taskAffinity屬性設為com.jg.zhang.androidtasktest.second時的啟動過程

 

  1. 在SecondActivity啟動ThirdActivity時,因為SecondActivity是singleInstance的,那麼設定ThirdActivity的啟動標誌為FLAG_ACTIVITY_NEW_TASK
  2. 然後獲得ThirdActivity的taskAffinity,即為com.jg.zhang.androidtasktest.second
  3. 檢查是否已經存在一個affinity為com.jg.zhang.androidtasktest.second的任務,這個任務是不存在的
  4.  建立一個新的affinity為com.jg.zhang.androidtasktest.second的任務,並且將ThirdActivity啟動到這個新的任務
到此singleInstance也介紹完了。

android Activity launch mode 一個執行個體 singleInstance

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.