這是說好的 面試系列 的第二期。本期我們依然來探討一些面試必考題。
往期內容傳遞:
Android 面試:說說 Android 的四種啟動模式
說說 Activity 的生命周期吧
當我告訴你面試官會問這個問題的時候,你一定是「啪」,給我一耳光。這樣的問題網上一搜一大堆,隨便背誦一下就可以輕松面過,有必要這么大費周折地來聽「南塵」吹一波嗎?
所以你開始背誦起來。
- 啟動 Activiy:onCreate => onStart() => onResume(), Activity 進入運行狀態.
- Activity 退居后臺 ( Home 或啟動新 Activity ): onPause() => onStop().
- Activity 返回前臺: onRestart() => onStart() => onResume().
- Activity 后臺期間內存不足情況下當再次啟動會重新執行啟動流程。
- 鎖屏: onPause() => onStop().
- 解鎖: onStart() => onResume().
干脆上張圖,更清晰。
咋一看還是挺清晰的,對,能背下來,甚至能把圖在心里記下來確實不錯。
但但是!!!
現在的面試官還會這樣問你嗎?
會!
對初級甚至是入門的 Android 開發工程師吧?
不賣關子,那怎么問呢?
怎么問之前,我想分別解析下這些方法,幫助大家理解。注意其中我加粗的部分。
onCreate()
每個活動中我們都重寫了這個方法, 它會在活動第一次被創建的時候調用。 你應該在這個方法中完成活動的初始化操作, 比如說加載布局、綁定事件等。onStart()
這個方法在活動由不可見變為可見的時候調用。onResume()
這個方法在活動準備好和用戶進行交互的時候調用。 此時的活動一定位于返回棧的棧頂,并且處于運行狀態。onPause()
這個方法在系統準備去啟動或者恢復另一個活動的時候調用。 我們通常會在這個方法中將一些及其消耗 CPU 的資源釋放掉(比如顯示地圖或者大規模圖形),以及保存一些關鍵數據(比如用戶輸入的數據等等),但這個方法的執行速度一定要快,不然會影響到新的棧頂活動的使用。onStop()
這個方法在活動完全不可見的時候調用。它和onPause()
方法的主要區別在于,如果啟動的新活動是一個對話框式的活動,那么onPause()
方法會得到執行,而onStop()
方法并不會執行。onDestroy()
這個方法在活動被銷毀之前調用,之后活動的狀態將變為銷毀狀態。onRestart()
這個方法在活動由停止狀態變為運行狀態之前調用,也就是活動被重新啟動了。
對官方代碼感興趣的童鞋可以去翻閱源碼,其中 Activity 單 onXXX 的回調方法 API 就高達八十多種,單純記憶下來根本沒用。額,可能有用,你可以為你超強的記憶力感到驕傲和自豪!
上面的幾種方法除了 onRestart()
以外,都兩兩相對,我們又可以分為三個時期。
完整生存期
活動在onCreate()
方法和onDestroy()
方法之間所經歷的,就是完整生存期。一般情況下,一個活動會在onCreate()
方法中完成各種初始化操作,而在onDestroy()
方法中完成釋放內存的操作。可見生存期
劃重點!!!這個問題我就在面試中遇到了,其實我知曉這個題,怎奈誤解了面試官的意思答非所問了。活動在onStart()
方法和onStop()
方法之間所經歷的,就是可見生存期。在可見生存期內, 活動對于用戶總是可見的, 即便有可能無法和用戶進行交互。 我們可以通過這兩個方法,合理地管理那些對用戶可見的資源。比如在onStart()
方法中對資源進行加載,而在onStop()
方法中對資源進行釋放, 從而保證處于停止狀態的活動不會占用過多內存。前臺生存期
活動在onResume()
方法和onPause()
方法之間所經歷的,就是前臺生存期。在前臺生存期內, 活動總是處于運行狀態的, 此時的活動是可以和用戶進行相互的, 我們平時看到和接觸最多的也這個狀態下的活動。
到底怎么問?
說了這么多,不妨我們可以模擬幾種面試官的詢問場景。
1、假設項目中有這樣的需求,當指定的 Activity 在用戶可見后才進行廣播的注冊,在用戶不可見后對廣播進行注銷,那應該在哪兩個回調中做這個處理呢?
2、如果有一些數據在 Activity 跳轉時(或者離開時)要保存到數據庫,那么你認為是在
onPause()
好還是在onStop()
執行這個操作好呢?3、Activity A 啟動了 Activity B,簡單說下它們分別的生命周期的變化。
4、Activity A 通過 Intent 顯示啟動了 Activity B,當 B 處于可見狀態后,A 是否一定會調用
onStop()
?
首先第一個問題,我們認真看了上面的解釋的童鞋肯定都比較清楚。問題中強調了「可見」和「不可見」,所以我們只需要注重可見生命周期,在Activity 啟動后,會先調用 onCreat()
方法進行布局和想關事件的綁定,直到回調 onStart()
方法后活動才可見,所以直接回答 onStart()
和 onStop()
即可。
第二個問題,熟悉 Activity 的生命周期的我們都知道,onPause()
相比 onStop()
更容易觸發。而「數據」就是 APP 甚至互聯網產品的根,我們雖然絕大多數情況下都會遵從 onPause()
=> onStop()
的原則,但我們實在難以保證每次運行都能正常運行到 onStop()
方法,比如還沒運行到 onStop()
系統就被回收了。
值得注意的是,這個操作要盡量地快,不然肯定會影響到下一個 Activity 的生命周期的。
第三個和第四個問題其實考察的點基本一致,大概就想考察面試者是否認為只要最上層棧頂的 Activity B 處于可見狀態,那下面一層的 Activity A 就一定會調用 onStop()
方法。
如果直接照第四個問題的方式提問你,你就算認定一定會調用,但你也會被問的懷疑人生。但由于你覺得一定調用 onStop()
方法,并且你也找不到不調用的情況,所以你很耿直的回答了一定會調用。
實際上卻并不是一定會調用,我們上面也說了,Activity 調用 onStop()
的時期是該 Activity 處于完全不可見狀態,所以我們只需要想辦法舉出還可見的狀態就好了。
我們假設彈出一個對話框形式的 Activity B,甚至就算彈出一個正常的 Activity B,把 B 的頁面設置較低的透明度,實際上是一樣的效果,不信你去打印日志試試。
上面提到了數據存儲要放在 onPause() 比較好,那么無論什么數據的保存都放在 onPause() 可行嗎?
哈哈,之前我也是認為是正確的,直到今天。
假設部分數據是非常重要的,我們需要在各種情況都要考慮到存儲起來,我之前也是用 onPause()
生命周期做的處理。
可當我直接關閉電源,再重啟的時候數據直接不見了!!!
想來也是應該的,直接關掉電源,誰還管你的 Activity 生命周期呢?最后我把重量級的數據存儲放在了當數據發生變動(一些人為操作,或從服務器獲取)的時候進行數據存儲。
小結
Activity 的生命周期好像我們平時沒怎么注意,因為覺得一切好像理所當然,但成功在于每一個細節,運用得當 Activity 的生命周期,讓你的應用更加暢行無阻。
咦,一轉眼都快到凌晨了,最近筆者的工作也是忙的飛起。但還是要馬不停蹄地裝逼,你看,「stormzhang」靠裝逼幫公司融資 XXX 萬,說明裝逼就是有效果的。
做不完的開源,寫不完的矯情。歡迎掃描下方二維碼或者公眾號搜索「nanchen」關注我的微信公眾號,目前多運營 Android ,盡自己所能為你提升。如果你喜歡,為我點贊分享吧~