Android四種啟動模式

_鐵樹開花發表於2020-12-28

先說顯式跳轉和隱式跳轉

我們在開發Android應用的時候,一般MainAcitvity會設定<action android:name=“android.intent.action.MAIN” />然後我們的系統就能找到我們app的啟動頁面了;這就是一個隱式跳轉,系統會根據action標籤去在我們的清單檔案manifest 中篩選出來我們設定的action.Main的activity作為第一個啟動的activity;包括系統裡的開啟相機、開啟檔案等等,都是隱身跳轉

//用來開啟相機的Intent
   Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
  //根據intent在系統中找到合適的應用的activity,如果有多個activity可選擇,
  //則會彈出ResolverActivity讓使用者選擇合適的應用。這個方法是在ActivityStack
  ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
                profileFile, profileFd, userId);

顯示 跳轉就比較簡單了,Intent intent = new Inent(this, LoginActivity.class);這個沒什麼好說的
效能方面肯定是顯示跳轉 要好於隱式跳轉了

四個跳轉模式

很簡單 在同一個 Task Stack任務中
1、standard只要是startActivity,就會重新建立信的activity
2、singTask 看activity是否存在,如果存在就會把已存在的activity拿到棧頂,並且銷燬在該activity之上的activity,顯示出來,還會在activity中執行onNewIntent方法,表示我當前的Intent是新的,我新start了;如果不存在就正常建立,也不會執行onNewIntent方法

protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
    }

3、singTop 這個就看這個activity是否在棧頂,如果在棧頂那麼跟singTask效果一樣,如果 不在棧頂和standard效果一樣;
4、singInstance 這個就是會開啟一個獨立的任務棧,只儲存一個當前型別的activity

還有一個問題:singleTask和singleInstance模式下,onAcitivityResult方法執行會有影響。要用onActivityResult方法,那麼這個目標activity一定不能是這種模式。

Flags

正常的啟動activity還可以設定Flags,可以set設定單個Flags也可以用add組合方式

        Intent intent = new Intent();
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        //也可以set
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

有這樣一個場景:登入Activity、註冊1、註冊2、註冊3;四個頁面
都是正常的standard 模式
當到註冊3頁面的時候,如果註冊完成,那麼直接跳到登入頁面,那麼就要把註冊1、2、3介面都finish()掉,如果註冊沒完成,可以挨個返回finish()掉;典型的一個註冊流程:
我們只需要這樣做

        Intent intent = new Intent(this, LoginActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);//與載入模式singleTop功能相同    
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);//銷燬目標Activity和它之上的所有Activity,重新建立目標Activity
        //這種啟動模式就相當於LoginActivity是singTask了,但是實際上又不是,動態新增的Flag達到的效果
        startActivity()

當然Flag還有很多很多種,列舉一些常用的

FLAG_ACTIVITY_CLEAR_TOP
例如現在的棧情況為:A B C D。D此時通過intent跳轉到B,如果這個intent新增FLAG_ACTIVITY_CLEAR_TOP標記,則棧情況變為:AB。如果沒有新增這個標記,則棧情況將會變成:A B C D B。也就是說,如果新增了FLAG_ACTIVITY_CLEAR_TOP標記,並且目標Activity在棧中已經存在,則將會把位於該目標activity之上的activity從棧中彈出銷燬。這跟上面把B的Launchmode設定成singleTask類似。
FLAG_ACTIVITY_NEW_TASK

例如現在棧1的情況是:A BC。C通過intent跳轉到D,並且這個intent新增了FLAG_ACTIVITY_NEW_TASK標記,如果D這個Activity在Manifest.xml中的宣告中新增了Taskaffinity,並且和棧1的affinity不同,系統首先會查詢有沒有和D的Taskaffinity相同的task棧存在,如果有存在,將D壓入那個棧,如果不存在則會新建一個D的affinity的棧將其壓入。如果D的Taskaffinity預設沒有設定,或者和棧1的affinity相同,則會把其壓入棧1,變成:A B CD,這樣就和不加FLAG_ACTIVITY_NEW_TASK標記效果是一樣的了。

注意:如果試圖從非activity的非正常途徑啟動一個activity,比如,從一個service中啟動一個activity,則intent必須要新增FLAG_ACTIVITY_NEW_TASK標記。

FLAG_ACTIVITY_NO_HISTORY

例如現在棧情況為:A BC。C通過intent跳轉到D,這個intent新增FLAG_ACTIVITY_NO_HISTORY標誌,則此時介面顯示D的內容,但是它並不會壓入棧中。如果按返回鍵,返回到C,棧的情況還是:AB C。如果此時D中又跳轉到E,棧的情況變為:A B C E,此時按返回鍵會回到C,因為D根本就沒有被壓入棧中。

FLAG_ACTIVITY_SINGLE_TOP:和上面Activity的Launchmode的singleTop類似。如果某個intent新增了這個標誌,並且這個intent的目標activity就是棧頂的activity,那麼將不會新建一個例項壓入棧中。

/Activity的主要屬性:(在AndroidManifest.xml中 )

allowTaskReparenting:設定成true時,和Intent的FLAG_ACTIVITY_NEW_TASK標記類似。

alwaysRetainTaskStat: 如果使用者長時間將某個task移入後臺,則系統會將該task的棧內容彈出只剩下棧底的activity,此時使用者再返回,則只能看到根activity了。如果棧底的activity的這個屬性設定成true,則將阻止這一行為,從而保留所有的棧內容。

clearTaskOnLaunch:根activity的這個屬性設定成true時,和上面的alwaysRetainTaskStat的屬性為true情況搞好相反。

finishOnTaskLaunch:對於任何activity,如果它的這個屬性設定成true,則當task被放置到後臺,然後重新啟動後,該activity將不存在了

相關文章