1. 程式人生 > 實用技巧 >Android開發筆記(十六)——Activity的4種啟動模式

Android開發筆記(十六)——Activity的4種啟動模式

AndroidManifest 中比較重要的一個屬性是 launchMode 啟動模式:

Acyivity的 android:launchMode 四個屬性:

  • standard:標準模式,預設
  • singleTop:Task棧頂複用模式(棧是先進後出,當我們啟動一個Activity,如果這個目標Activity位於棧頂,不會建立一個新的例項,而是會直接複用這個棧頂的Activity)
  • singleTask:Task棧內複用模式(不一定要在棧頂,只要棧內有就可以直接複用,不管位置)
  • singleInstance:全域性單例模式(前兩個必須是在同一個棧內,這個是隻要在存取的所有棧裡面只要有的就可以複用)

測試準備

繼續使用上次建立的AActivity和BActivity。

在AActivity中的onCreate函式中新增:

Log.d("AActivity","-----onCreate-----");
Log.d("AActivity","---taskid:"+getTaskId()+"---   ---hash:"+hashCode()+"---");
logtaskName();  //列印任務棧的名稱

onNewIntentlogtaskName 函式寫在onCreate函式後面:

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        Log.d("AActivity","-----onNewIntent-----");
        Log.d("AActivity","---taskid:"+getTaskId()+"---   ---hash:"+hashCode()+"---");
        logtaskName();  //列印任務棧的名稱
    }

    private void logtaskName(){
        try {
            ActivityInfo info = getPackageManager().getActivityInfo(getComponentName(), PackageManager.GET_META_DATA);
            Log.d("AActinity",info.taskAffinity); //info.taskAffinity可以理解為當前Activity所在任務棧的名稱
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
    }

在BActivity中同樣操作,在A新增一個Button使其在A頁面跳轉到A頁面,在B新增一個Button使其在B頁面跳轉到A頁面。

standard

  • Activity是由任務棧管理的,每啟動一個Activity,就會被放入棧中,按返回鍵,就會從棧頂移除一個Activity。
  • standard是預設的啟動模式,即標準模式。每啟動一個Activity,都會建立一個新的例項。

演示

  • 從主頁面MainActivity跳轉到AActivity中時,MainActivity的任務棧為包名,後面所有的Activity都隸屬於這個棧
  • 當沒有設定任務棧的名稱時候,預設為應用的包名
  • 當點選Button從A頁面跳轉到A頁面時,這裡taskid是一樣的,也就是這兩個Activity處在同一個任務棧當中,但是他們的雜湊碼是不一樣的,表示這兩個Activity不是同一個例項,說明從A頁面跳轉到A頁面時又建立了一個新的例項。(因為是標準啟動,每啟動一個Activity,都會建立一個新的例項
  • 當點選Jump從A頁面跳轉到B頁面時:可以看到任務棧還是相同的,但是雜湊碼不同,因為BActivity本身不存在於任務棧當中,是一個新的例項

singleTop

  • 當要啟動的目標Activity已經位於棧頂時,不會建立新的例項,會複用棧頂的Activity,並且其 onNewIntent() 方法會被呼叫;
  • 如果目標Activity不在棧頂(在棧裡但不在頂部;或者根本不在棧內),則和standard一樣建立新的例項。

演示

  • 從主頁面MainActivity跳轉到AActivity中時,呼叫onCreate方法
  • 從AActivity再次跳轉到AActivity中時(此時目標Activity是AActivity,目標Activity在棧頂中),這時打印出來的雜湊碼和之前一直,也就是說此時複用了棧頂的Activity,並且其onNewIntent()方法被呼叫
  • 從AActivity跳轉到BActivity中時(此時目標Activity是BActivity,目標Bctivity不在棧中),此時雜湊碼發生了變化,說明建立了新的例項。
  • 從BActivity再次跳轉到AActivity中時(此時目標Activity是AActivity,目標Activity在棧中但是不在棧頂中),此時雜湊碼發生了變化,說明建立了新的例項。

singleTask

  • 在同一個任務棧中,如果要啟動的目標Activity已經在棧中,則會複用該Activity,並呼叫其 onNewIntent() 方法,並且該Activity上面的Activity會被清除(出棧)
  • 如果棧中沒喲,則建立新的例項。

當沒有設定任務棧的名稱時候,預設為應用的包名,如果自己有設定任務棧名稱(在 AndroidManifast 中對應的activity設定屬性 android:taskAffinity ),那就不屬於預設包名的任務棧了。當從這個Activity開始啟其他Activity時候,都會被加入這個新設定的棧中。

singleInstance

  • 全域性複用,不管哪個Task棧,只要存在目標Activity就複用;
  • 每個Activity佔有一個新的Task棧。

通常使用standard和singleTop、singleTask,singleInstance用的比較少。