android當中taskAffinity屬性與launchMode相關

1、本文嘗試解釋如下問題android

1.  Activity被啓動以後放在哪一個任務棧當中?與哪些因素有關?app

2.  Activity的四種啓動模式對Activity的啓動有哪些影響?ide

3.  在Activity中使用startActivityForResult(intent, REQUESTCODE);和onActivityResult()
測試

    是否與被啓動的ActivitylaunchMode有關?若是有關,有什麼關係?this

2、Activity被啓動以後放在哪一個任務棧當中?與哪些因素有關?spa

1.基本論斷:Activity啓動以後對應的任務站與Activity的兩個屬性taskAffinityallowTask-xml

Reparenting有關生命週期

  2.原理utf-8

(1)任務棧的標識----任務棧名稱的肯定文檔

    任務棧的標識是由任務棧的名稱來肯定的,例如,在一般狀況下用包名標識一個惟一任務棧,清單文件以下:

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

    package="com.example.musictest01"

    android:versionCode="1"

    android:versionName="1.0" >

    <uses-sdk

        android:minSdkVersion="8"

        android:targetSdkVersion="17" />

    <application

        android:allowBackup="true"

        android:theme="@style/AppTheme" >

        <activity

            android:name="com.example.musictest01.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=".AActivity"></activity>

        <activity android:name=".BActivity"></activity>

    </application>

</manifest>

     該文件當中<appliacation><activity>標籤都沒有設置taskAffinity屬性,因此這個應用的默認任務棧名稱就是包名"com.example.musictest01" , activity默認也會放入這個任務棧當中。

    <application>當中的屬性android:taskAffinity指定該應用程序默認的任務棧名稱,用來標識一個惟一的任務棧,若是不設置,則默認爲包名

    <activity>當中的屬性android:taskAffinity指定該activity的「宿主」任務棧名稱

(2)情景分析:

第一步、定義宿主工程,其Manifest.xml文件以下:(ADT建立,不作任何修改)

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

    package="com.example.master"

……>

    <application

        android:allowBackup="true"

        android:icon="@drawable/ic_launcher"

        android:label="@string/app_name"

        android:theme="@style/AppTheme">

        <activity

            android:name="com.example.master.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>

    </application>

</manifest>

第二步、定義奴隸工程,Manifest.xml以下(activityandroid:taskAffinity="com.example

.master")

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

    package="com.example.slave"

    ……>

    <application

        android:allowBackup="true"

        android:icon="@drawable/ic_launcher"

        android:label="@string/app_name"

        android:theme="@style/AppTheme" >

        <activity

            android:name="com.example.slave.MainActivity"

            android:label="@string/app_name"

            android:taskAffinity="com.example.master">

            <intent-filter>

                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>

        </activity>

        <activity

            android:name=".AActivity">

        </activity>

        <activity android:name=".BActivity">

        </activity>

    </application>

</manifest>

第三步、結果 

     當咱們啓動宿主工程,按home鍵將宿主任務棧放到後臺,而後啓動奴隸工程,神奇的事情發生了:奴隸工程的MainActivity並無被加載,而是顯示的是宿主工程的MainActivity

第四步、 一樣道理,反過來執行,咱們首先啓動奴隸工程,MainActivity-->AActivity-->BActivity,home鍵,回到桌面啓動宿主工程,結果並無加載宿主工程的MainActivity,而是顯示的是奴隸工程的BActivity.

第五步、結論

   android:taskAffinity="com.example.master" 此屬性指定了該activity所在的任務棧名稱,若是系統當中已經存在指定的任務棧,那麼該activity啓動的時候會從新寄宿到宿主當中(這是android的官方說明,可是在實際的實踐中發現,啓動該activity的時候僅僅是將指定的任務棧推到前臺,顯示該任務棧最頂端的那個原activity,本activity並無被建立,換言之,該activity的生命週期的相關方法並無被執行);

       若是系統當中沒有指定的任務棧,那麼系統會建立名爲com.example.master 的任務棧,並將該activity放入到建立的任務棧當中。

第六步、詭異的事情:按照android官方文檔的說明,宿主的activity當中應該要設置android:allow-

TaskReparenting="true",可是實驗代表,不設置該屬性亦可!

 

3. 與啓動模式相結合的情景

3.1 android:taskAffinity FLAG_ACTIVITY_NEW_TASK結合

(1)基本論斷

若是加載某個ActivityintentFlag被設置成FLAG_ACTIVITY_NEW_TASK時,它會首先檢查是否存在與本身taskAffinity相同的Task,若是存在,那麼它會直接宿主到該Task中,若是不存在則從新建立Task 

(2)測試。 
      
咱們首先寫一個應用,它有兩個ActivityActivity1Activity2),AndroidManifest.xml以下: 

<application

android:icon="@drawable/icon" android:label="@string/app_name"> 
    <activity android:name=".Activity1" 
                  
android:taskAffinity="com.example.task" 
      android:label="@string/app_name"> 
    </activity> 
    <activity android:name=".Activity2"> 
      <intent-filter> 
          <action android:name="android.intent.action.MAIN" /> 
           <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 
 </application> 

 Activity2的代碼以下:

public class Activity2 extends Activity {  
        private static final String TAG = "Activity2";  
        @Override 
        protected void onCreate(Bundle savedInstanceState) {  
            super.onCreate(savedInstanceState);  
            setContentView(R.layout.main2);    
        }  
        @Override 
        public boolean onTouchEvent(MotionEvent event) {  
            Intent intent = new Intent(this, Activity1.class);  
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
            startActivity(intent);  
            return super.onTouchEvent(event);  
        }  
    } 

//activity1的啓動模式改成new task ,並設置android:taskAffinity="com.example.task"

而後,咱們再寫一個應用MyActivity,它包含一個ActivityMyActivity),AndroidManifest.xml以下: 
<application

android:icon="@drawable/icon" android:label="@string/app_name"> 
    <activity android:name=".MyActivity" 
      
android:taskAffinity="com.example.task"
 
      android:label="@string/app_name"> 
     <intent-filter> 
      <action android:name="android.intent.action.MAIN"/> 
     <category android:name="android.intent.category.LAUNCHER"/> 
     </intent-filter> 
   </activity> 
    咱們首先啓動MyActivity,而後按Home鍵,返回到桌面,而後打開Activity2,點擊Activity2,進入Activity1(他的啓動模式是new_task)。而後按返回鍵。 
           
咱們發現,咱們進入Activity的順序爲Activity2->Activity1,而返回時順序爲 Activity1->MyActivity。這就說明了一個問題,Activity1在啓動時,從新宿主到了MyActivity所在的Task 中去了。

3.2 android:taskAffinity singleTask結合

 

    直接給結論:

    當一個應用程序加載一個singleTask模式的Activity時,首先該Activity會檢查是否存在與它的taskAffinity相同的Task

    (1)、若是存在,那麼檢查是否實例化,若是已經實例化,那麼銷燬在該Activity以上的Activity並調用該ActivityonNewIntent()。若是沒有實例化,那麼該Activity實例化併入棧。

(2)、若是不存在,那麼就從新建立Task,併入棧。

 

3.3 android:taskAffinity singleInstance結合

 

直接給出結論:

         (1)、當一個應用程序加載一個singleInstance模式的Activity時,若是該Activity沒有被實例化,那麼就從新建立一個Task,併入棧,若是已經被實例化,那麼就調用該ActivityonNewIntent

(2)singleInstanceActivity所在的Task不容許存在其餘Activity,任何從該Activity加載的其它 Actiivty(假設爲Activity2)都會被放入其它的Task中,若是存在與Activity2相同affinityTask,則在該 Task內建立Activity2。若是不存在,則從新生成新的Task併入棧。

(3) 若是在奴隸應用application1當中定義兩個activity,MainActivity和AActivity,將AActivity的啓動模式設置爲singleInstance,並設置其taskAffinity爲com.example.master; 從MainActivity中啓動AActivity,毫無疑問,此時會建立一個新的任務棧,名稱是com.example.master,並將AActivity放置到棧中。而後將application1置於後臺(按HOME鍵)。

打開宿主應用application2(默認的任務棧名稱是com.example.master),此時驚奇地發現:此應用打開的是application1的AActivity,按後退鍵,退回到application2的MainActivity,由此能夠看出,當聲明爲singleInstance的activity所在的任務棧被其餘應用程序使用的時候,這個任務棧裏面的原activity會喪失原來的singleInstance要求的一個activity在一個任務棧當中的屬性,可是請注意:原來的這個activity始終是在棧頂的,後來加入的activity會都在這個activity的下面,可是仍是按照棧的形式進出規則!

    (4)將上面的過程反過來,若是首先啓動application2,系統當中存在了com.example.master 任務棧,而後啓動SingleInstanceActivity,雖然他指定了taskAffinity,可是仍然不能將本身寄宿到com.example.master任務棧當中!他會從新開一個任務棧將本身放進去!

3、Activity的四種啓動模式對Activity的啓動有哪些影響?

重點說一下 singleTask,直接給結論:

1. 設置了"singleTask"啓動模式的Activity,它在啓動的時候,會先在系統中查找屬性值affinity,等於它的屬性值taskAffinity的任務棧是否存在存在;若是存在這樣的任務棧,它就會在這個任務棧中啓動,不然就會在新任務棧中啓動。所以,若是咱們想要設置了"singleTask"啓動模式的Activity在新的任務中啓動,就要爲它設置一個獨立的taskAffinity屬性值。

      2. 若是設置了"singleTask"啓動模式的Activity不是在新的任務中啓動時,它會在已有的任務中查看是否已經存在相應的Activity實例,若是存在,就會把位於這個Activity實例上面的Activity所有結束掉,即最終這個Activity實例會位於任務的堆棧頂端中(這個過程會調用該ActivityonNewIntent())

 

4、在Activity中使用startActivityForResult(intent, REQUESTCODE);onActivityResult()

是否與被啓動的ActivitylaunchMode有關?若是有關,有什麼關係?

1.一般狀況下,當launchMode設置爲standard或者singleTop的時候,程序的執行流程以下所示

2.若是launchMode設置爲singleTask或者singleInstance的時候,程序就會在setResult以前調用

 onActivityResult(),這樣就得不到從activity2返回的數據,因此須要注意!!!

相關文章
相關標籤/搜索