目錄
1.Android四種Activity啓動方式:
- 標準模式(standard)
- 棧頂複用模式(singleTop)
- 棧內複用模式(singleTask)
- 單例模式(singleInstance)
啓動模式可在AndroidManifest.xml中,通過<activity>標籤的android:launchMode屬性設置。
2.啓動模式的結構——棧(後進先出)
任務棧(Task Stack)或者叫退回棧(Back Stack)介紹:
1.任務棧用來存放用戶開啓的Activity。
2.在應用程序創建之初,系統會默認分配給其一個任務棧(默認一個),並存儲根Activity。
3.同一個Task Stack,只要不在棧頂,就是onStop狀態:
4.任務棧的id自增長型,是Integer類型。
5.新創建Activity會被壓入棧頂。點擊back會將棧頂Activity彈出,併產生新的棧頂元素作爲顯示界面(onResume狀態)。
6.當Task最後一個Activity被銷燬時,對應的應用程序被關閉,清除Task棧,但是還會保留應用程序進程(狂點Back退出到Home界面後點擊Menu會發現還有這個App的框框。個人理解應該是這個意思),再次點擊進入應用會創建新的Task棧。
3.啓動方式詳解
3.1標準模式
特點:1.Activity的默認啓動模式
2.每啓動一個Activity就會在棧頂創建一個新的實例。
應用場景: 絕大多數Activity,mainfest中沒有配置就默認標準模式。如果以這種方式啓動的Activity被跨進程調用,在5.0之前新啓動的Activity實例會放入發送Intent的Task的棧的頂部,儘管它們屬於不同的程序,這似乎有點費解看起來也不是那麼合理,所以在5.0之後,上述情景會創建一個新的Task,新啓動的Activity就會放入剛創建的Task中,這樣就合理的多了。
缺點:當Activity已經位於棧頂時,而再次啓動Activity時還需要在創建一個新的實例,不能直接複用。
3.2 singleTop模式(棧頂複用)
如果需要新建的Activity位於任務棧棧頂,那麼此Activity的實例就不會重建,而是重用棧頂的實例。並回調如下方法: 由於不會重建一個Activity實例,則不會回調其他生命週期方法。
@Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); }
應用場景:
- 在通知欄點擊收到的通知,然後需要啓動一個Activity,這個Activity就可以用singleTop,否則每次點擊都會新建一個Activity。
- 當然實際的開發過程中,測試妹紙沒準給你提過這樣的bug:某個場景下連續快速點擊,啓動了兩個Activity。如果這個時候待啓動的Activity使用 singleTop模式也是可以避免這個Bug的。同standard模式,如果是外部程序啓動singleTop的Activity,在Android 5.0之前新創建的Activity會位於調用者的Task中,5.0及以後會放入新的Task中。
3.3singleTask模式(棧內複用)
- 特點:
該模式是一種單例模式,即一個棧內只有一個該Activity實例。每次啓動Activity時系統首先檢查棧中是否存在當前Activity實例。如果存在則直接複用,並把當前Activity之上所有實例全部出棧。
- 應用場景:
大多數App的主頁。對於大部分應用,當我們在主界面點擊回退按鈕的時候都是退出應用,那麼當我們第一次進入主界面之後,主界面位於棧底,以後不管我們打開了多少個Activity,只要我們再次回到主界面,都應該使用將主界面Activity上所有的Activity移除的方式來讓主界面Activity處於棧頂,而不是往棧頂新加一個主界面Activity的實例,通過這種方式能夠保證退出應用時所有的Activity都能報銷燬。在跨應用Intent傳遞時,如果系統中不存在singleTask Activity的實例,那麼將創建一個新的Task,然後創建SingleTask Activity的實例,將其放入新的Task中。
- 應用案例
例如瀏覽器的主界面。不管從多少個應用啓動瀏覽器,只會啓動主界面一次,其餘情況都會走onNewIntent,並且會清空主界面上面的其他頁面。
3.4singleInstance模式(單例模式)
- 特點:
該模式的Activity會啓動一個新的任務棧來管理Activity實例,並且該實例在整個系統中只有一個。無論從那個任務棧 中啓動該Activity,都會是該Activity所在的任務棧轉移到前臺,從而使Activity顯示。主要作用是爲了在不同程序中共享一個Activity。
- 應用場景:
系統Launcher、鎖屏鍵、來電顯示等系統應用。
4.Activity啓動流程
(涉及源碼,我就不多贅述了,大致流程走一下)
- Activity的啓動流程一般是通過調用startActivity或者是startActivityForResult來開始的
- startActivity內部也是通過調用startActivityForResult來啓動Activity,只不過傳遞的requestCode小於0
- Activity的啓動流程涉及到多個進程之間的通訊這裏主要是ActivityThread與ActivityManagerService之間的通訊
- ActivityThread向ActivityManagerService傳遞進程間消息通過ActivityManagerNative,ActivityManagerService向ActivityThread進程間傳遞消息通過IApplicationThread。
- ActivityManagerService接收到應用進程創建Activity的請求之後會執行初始化操作,解析啓動模式,保存請求信息等一系列操作。
- ActivityManagerService保存完請求信息之後會將當前系統棧頂的Activity執行onPause操作,並且IApplication進程間通訊告訴應用程序繼承執行當前棧頂的Activity的onPause方法;
- ActivityThread接收到SystemServer的消息之後會統一交個自身定義的Handler對象處理分發;
- ActivityThread執行完棧頂的Activity的onPause方法之後會通過ActivityManagerNative執行進程間通訊告訴ActivityManagerService,棧頂Actiity已經執行完成onPause方法,繼續執行後續操作;
- ActivityManagerService會繼續執行啓動Activity的邏輯,這時候會判斷需要啓動的Activity所屬的應用進程是否已經啓動,若沒有啓動則首先會啓動這個Activity的應用程序進程;
- ActivityManagerService會通過socket與Zygote繼承通訊,並告知Zygote進程fork出一個新的應用程序進程,然後執行ActivityThread的mani方法;
- 在ActivityThead.main方法中執行初始化操作,初始化主線程異步消息,然後通知ActivityManagerService執行進程初始化操作;
- ActivityManagerService會在執行初始化操作的同時檢測當前進程是否有需要創建的Activity對象,若有的話,則執行創建操作;
- ActivityManagerService將執行創建Activity的通知告知ActivityThread,然後通過反射機制創建出Activity對象,並執行Activity的onCreate方法,onStart方法,onResume方法;
- ActivityThread執行完成onResume方法之後告知ActivityManagerService onResume執行完成,開始執行棧頂Activity的onStop方法;
- ActivityManagerService開始執行棧頂的onStop方法並告知ActivityThread;
- ActivityThread執行真正的onStop方法;
2019.5.27更新