當面試官問怎麼理解 onStart可見但不可交互時,Android開發千萬不要小瞧了這個問題!

前言

今天朋友遇到一個面試題,分享給大家:

onStart生命週期表示Activity可見,那爲什麼不能交互呢?

這個問題看似簡單,但涉及到的面還是比較多的,比如Activity生命週期的理解,進程的理解,以及View繪製的時機。

一起看看吧。

onStart介紹

首先,是關於onStart生命週期的理解。

官網是這麼介紹的:

當 Activity 進入“已開始”狀態時,系統會調用此回調。onStart() 調用使 Activity 對用戶可見,因爲應用會爲 Activity 進入前臺並支持互動做準備。

對用戶可見?

奇怪了,對用戶可見,不就是我們可以看到了嗎,爲什麼又不能互動呢?

更何況onStart 的時候界面都還沒繪製,該怎麼理解這個可見呢?

做個小實驗

首先,科普官方定義的兩個狀態。

  • onStart到onStop中間的狀態叫做“已開始”狀態。
  • onResume到onPause中間的狀態叫做“已恢復”狀態。

然後我們做個小實驗,定義ActivityAActivityBActivityB爲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一起使用,即onStartonStop這個階段叫做 可見 階段。

而真正顯示出來可以進行交互 發生在onResume之後,也就是View繪製出來,並處於前臺的時候。

面試前做好準備戰!

接下來將分享面試的一個複習路線,如果你也在準備面試但是不知道怎麼高效複習,可以參考一下我的複習路線,有任何問題也歡迎一起互相交流,加油吧!

這裏給大家提供一個方向,進行體系化的學習:

1、看視頻進行系統學習

前幾年的Crud經歷,讓我明白自己真的算是菜雞中的戰鬥機,也正因爲Crud,導致自己技術比較零散,也不夠深入不夠系統,所以重新進行學習是很有必要的。我差的是系統知識,差的結構框架和思路,所以通過視頻來學習,效果更好,也更全面。關於視頻學習,個人可以推薦去B站進行學習,B站上有很多學習視頻,唯一的缺點就是免費的容易過時。

另外,我自己也珍藏了好幾套視頻,有需要的我也可以分享給你。

2、進行系統梳理知識,提升儲備

客戶端開發的知識點就那麼多,面試問來問去還是那麼點東西。所以面試沒有其他的訣竅,只看你對這些知識點準備的充分程度。so,出去面試時先看看自己複習到了哪個階段就好。

系統學習方向:

  • 架構師築基必備技能:深入Java泛型+註解深入淺出+併發編程+數據傳輸與序列化+Java虛擬機原理+反射與類加載+動態代理+高效IO

  • Android高級UI與FrameWork源碼:高級UI晉升+Framework內核解析+Android組件內核+數據持久化

  • 360°全方面性能調優:設計思想與代碼質量優化+程序性能優化+開發效率優化

  • 解讀開源框架設計思想:熱修復設計+插件化框架解讀+組件化框架設計+圖片加載框架+網絡訪問框架設計+RXJava響應式編程框架設計+IOC架構設計+Android架構組件Jetpack

  • NDK模塊開發:NDK基礎知識體系+底層圖片處理+音視頻開發

  • 微信小程序:小程序介紹+UI開發+API操作+微信對接

  • Hybrid 開發與Flutter:Html5項目實戰+Flutter進階

知識梳理完之後,就需要進行查漏補缺,所以針對這些知識點,我手頭上也準備了不少的電子書和筆記,這些筆記將各個知識點進行了完美的總結。

3、讀源碼,看實戰筆記,學習大神思路

“編程語言是程序員的表達的方式,而架構是程序員對世界的認知”。所以,程序員要想快速認知並學習架構,讀源碼是必不可少的。閱讀源碼,是解決問題 + 理解事物,更重要的:看到源碼背後的想法;程序員說:讀萬行源碼,行萬種實踐。

主要內含微信 MMKV 源碼、AsyncTask 源碼、Volley 源碼、Retrofit源碼、OkHttp 源碼等等。

4、面試前夕,刷題衝刺

面試的前一週時間內,就可以開始刷題衝刺了。請記住,刷題的時候,技術的優先,算法的看些基本的,比如排序等即可,而智力題,除非是校招,否則一般不怎麼會問。

關於面試刷題,我個人也準備了一套系統的面試題,幫助你舉一反三:

還有耗時一年多整理的一系列Android學習資源:Android源碼解析、Android第三方庫源碼筆記、Android進階架構師七大專題學習、歷年BAT面試題解析包、Android大佬學習筆記等等。

以上這些內容均免費分享給大家,需要完整版的朋友,點這裏可以看到全部內容。或者關注主頁掃描加 【微信】 獲取。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章