前言
今天朋友遇到一個面試題,分享給大家:
onStart生命周期表示Activity可見,那為什么不能交互呢?
這個問題看似簡單,但涉及到的面還是比較多的,比如Activity生命周期的理解,進程的理解,以及View繪制的時機。
一起看看吧。
onStart介紹
首先,是關於onStart生命周期的理解。
官網是這么介紹的:
當 Activity 進入“已開始”狀態時,系統會調用此回調。onStart() 調用使 Activity 對用戶可見,因為應用會為 Activity 進入前台並支持互動做准備。
對用戶可見?
奇怪了,對用戶可見,不就是我們可以看到了嗎,為什么又不能互動呢?該怎么理解這個可見呢?
做個小實驗
首先,科普官方定義的兩個狀態。
- onStart到onStop中間的狀態叫做
“已開始”
狀態。 - onResume到onPause中間的狀態叫做
“已恢復”
狀態。
然后我們做個小實驗,定義ActivityA
和 ActivityB
,ActivityB
為Dialog主題,ActivityA
中點擊可以跳轉到B:
image.setOnClickListener {
startActivity(Intent(this, ActivityB::class.java))
}
<activity android:name=".activity.ActivityB"
android:theme="@style/Theme.AppCompat.Light.Dialog"
android:launchMode="standard">
</activity>
進入ActivityA后,點擊按鈕,跳轉到B,這時候A的生命周期走到了onPause
,也就是回到了已開始
狀態。
這個時候,界面是這個樣子:
ActivityA處在已開始狀態,對用戶可見。
這里的可見是不是就很好理解了,確實對我們可見了,只不過 不在前台,不能交互。
所以延伸到普通的Activity
,這個可見,並不是表示用戶能用肉眼看到了,而是想表達:
Activity
已經顯示出來了,但是還不在前台
,所以只是可見
,但不可交互。
這個可見狀態是從onStart開始,onStop結束,我們可以分為兩個階段:
- onStart到onResume。這個階段,Activity被創建,布局已加載,但是界面還沒繪制,可以說界面都不存在。
- onPause到onStop。這個階段,就是我們剛才所做的實驗,Activity有界面,只是被新的界面所遮擋,也就是不在前台。
所以綜合兩個階段,我們把這種Activity被創建或已經顯示出來,但是不在前台,介於兩者之間的狀態叫做 可見
狀態。
onStart 和 onResume
到此,我們知道了可見的意思,其實也就知道了另外一個問題,也就是為什么要設計出onStart和onResume這兩種狀態。
onStart和onStop
,是從Activity是否可見的角度設計的。onResume和onPause
,是從Activity是否位於前台的角度設計的。
所以Activity
的生命周期又可以解釋為:
被創建(onCreate)——> 可見(onStart)——> 位於前台(onResume)——> 可見但不在前台(onPause)
可見進程
從另外的角度看,這個可見 可以指的是 可見進程。
這就涉及到進程的分類。
為了確定在內存不足時應該終止哪些進程,Android 會根據每個進程中運行的組件以及這些組件的狀態,將它們放入“重要性層次結構”。這些進程類型包括(按重要性排序):前台進程,可見進程,服務流程,緩存進程
這些進程是什么意思呢?
前台進程
是用戶目前執行操作所需的進程。比如 正在用戶的互動屏幕上運行一個 Activity(其 onResume() 方法已被調用)可見進程
是正在進行用戶當前知曉的任務。比如 正在運行的 Activity 在屏幕上對用戶可見,但不在前台(其 onPause() 方法已被調用)服務流程
包含一個已使用 startService() 方法啟動的 Service。緩存進程
是目前不需要的進程。比如 當前不可見的一個或多個 Activity 實例(onStop() 方法已被調用並返回)
所以Activity的生命周期又可以通過進程分為:
可見進程(onStart)——> 前台進程(onResume)——> 可見進程(onPause)——> 緩存進程(onStop)
這些進程有什么用呢?
我們都知道,在Android系統中有很多很多運行中的APP,也就代表了不同的進程。
當內存不夠時(達到了某個閾值),系統首先會通過onTrimMemory()回調方法告訴應用,讓應用自己來處理低內存情況下的減少內存操作。
這之后,如果內存還是很緊張,那么就會開始對一些進程的殺除,以釋放內存。這里就需要判斷進程的優先級了,從低優先級開始按順序終止進程。
所以,進程的分類作用就在這了。優先級的高低其實就代表了 終止進程的順序,也代表了對用戶的影響程度。
當然實際代碼中,進程優先級是有數字表示的,也就是ADJ,而上面說的進程類型都有相應的進程優先級數字范圍。比如:
public final class ProcessList {
//可見進程
static final int VISIBLE_APP_ADJ = 100;
// 前台進程
static final int FOREGROUND_APP_ADJ = 0;
// 服務進程
static final int SERVICE_ADJ = 500;
// 緩存進程
static final int CACHED_APP_MIN_ADJ = 900;
//...
}
再回到我們的問題上來:
其中,可見進程這里也出現了可見的概念,給出的解釋是:用戶知曉
。
當我們點擊一個頁面,我們知道這個頁面將要顯示出來,也知道之前的頁面在這個頁面后面。所以這些頁面和進程都是我們所知曉的,只是不在前台。
所以onStart
表示的可見,也可以理解為可見進程
,意思是這個Activity所在的進程任務已經被創建並顯示,我們知曉它,只是沒在前台。
可交互
那么可以交互到底是發生在什么階段呢?
之前我們說過,在Activity啟動過程中,調用了handleResumeActivity
方法。在這個方法中,調用了onResume
方法和addView
方法,完成了View的第一次繪制,並顯示到界面上。
@Override
public void handleResumeActivity() {
//onResume
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
//addView
if (r.window == null && !a.mFinished && willBeVisible) {
wm.addView(decor, l);
}
}
所以到onResume,View才被繪制出來,並顯示到前台。
官網是這么解釋onResume
的:
Activity 會在進入“已恢復”狀態時來到前台,然后系統調用 onResume() 回調。這是應用與用戶互動的狀態。應用會一直保持這種狀態,直到某些事件發生,讓焦點遠離應用。此類事件包括接到來電、用戶導航到另一個 Activity,或設備屏幕關閉。
所以可交互狀態應該是在onResume
之后,也就是Activity
可見並且處於前台。
小結
總結下:
onStart
狀態表示Activity
可見,而可見表示的意思是Activity
被創建出來了,被用戶所知曉,但是不在前台,還沒繪制界面,所以無法交互。也可以意指其所在的進程為可見進程。
其可見之意應該和onStop
一起使用,即onStart
到onStop
這個階段叫做 可見 階段。
而真正顯示出來可以進行交互 發生在onResume
之后,也就是View繪制出來,並處於前台的時候。
參考
《Android開發藝術探索》
https://juejin.cn/post/6896751245722615815
https://juejin.cn/post/6891911483379482637
拜拜
感謝大家的閱讀,有一起學習的小伙伴可以關注下我的公眾號——碼上積木❤️❤️
每日一個知識點,積少成多,建立知識體系架構。
這里有一群很好的Android小伙伴,歡迎大家加入~