Android 面試(二):如何理解 Activity 的生命周期

這是說好的 面試系列 的第二期。本期我們依然來探討一些面試必考題。

往期內容傳遞:
Android 面試:說說 Android 的四種啟動模式

說說 Activity 的生命周期吧

當我告訴你面試官會問這個問題的時候,你一定是「啪」,給我一耳光。這樣的問題網上一搜一大堆,隨便背誦一下就可以輕松面過,有必要這么大費周折地來聽「南塵」吹一波嗎?

nanchen

所以你開始背誦起來。

  • 啟動 Activiy:onCreate => onStart() => onResume(), Activity 進入運行狀態.
  • Activity 退居后臺 ( Home 或啟動新 Activity ): onPause() => onStop().
  • Activity 返回前臺: onRestart() => onStart() => onResume().
  • Activity 后臺期間內存不足情況下當再次啟動會重新執行啟動流程。
  • 鎖屏: onPause() => onStop().
  • 解鎖: onStart() => onResume().

干脆上張圖,更清晰。


nanchen

咋一看還是挺清晰的,對,能背下來,甚至能把圖在心里記下來確實不錯。

但但是!!!

現在的面試官還會這樣問你嗎?

會!

對初級甚至是入門的 Android 開發工程師吧?

nanchen

不賣關子,那怎么問呢?

怎么問之前,我想分別解析下這些方法,幫助大家理解。注意其中我加粗的部分。

  • 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

做不完的開源,寫不完的矯情。歡迎掃描下方二維碼或者公眾號搜索「nanchen」關注我的微信公眾號,目前多運營 Android ,盡自己所能為你提升。如果你喜歡,為我點贊分享吧~


nanchen
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容