Activity 的 36 大難點(diǎn),你會(huì)幾個(gè)?「建議收藏」

Android

前言

  • 學(xué) Android 有一段時(shí)間了,一直都只顧著學(xué)新的東西,最近發(fā)現(xiàn)很多平常用的少的東西竟讓都忘了,趁著這兩天,打算把有關(guān) Activity 的內(nèi)容以問(wèn)題的形式梳理出來(lái),也供大家查缺補(bǔ)漏。

本文中,我將一改往日寫(xiě)博客的習(xí)慣,全文用 XMind 將所有知識(shí)點(diǎn)以思維導(dǎo)圖的形式呈現(xiàn),歡迎大家食用~~

文章目錄


文章目錄

方便大家學(xué)習(xí),我在 GitHub 上建立個(gè) 倉(cāng)庫(kù)


神圖


  • 在開(kāi)始之前,先讓我們看看 Androidactivity 到底都有哪些東西?
  • 借一張網(wǎng)上很火的圖帶你了解 Activity
一張圖帶你了解 Activity

一、 生命周期


  • 先貼一張聞名遐邇的圖
  • 我們生命周期先看看具體有哪些方法回調(diào),在逐一攻破:

[圖片上傳失敗...(image-76615c-1572405738902)]

1.1 Dialog 彈出時(shí)

dialog彈出時(shí)
  • 如果是單純是創(chuàng)建的 dialogActivity 并不會(huì)執(zhí)行生命周期的方法
  • 但是如果是跳轉(zhuǎn)到一個(gè)不是全屏的 Activity 的話, 當(dāng)然就是按照正常的生命周期來(lái)執(zhí)行了
  • onPasue() -> onPause() ( 不會(huì)執(zhí)行原 ActivityonStop() , 否則上個(gè)頁(yè)面就不顯示了 )

1.2 橫豎屏切換時(shí)

橫豎屏切換時(shí)
  • 不設(shè)置 Activityandroid:configChanges 時(shí),切屏?xí)匦抡{(diào)用各個(gè)生命周期,切橫屏?xí)r會(huì)執(zhí)行一次,切豎屏?xí)r會(huì)執(zhí)行兩次

  • 設(shè)置 Activityandroid:configChanges="orientation" 時(shí),切屏還是會(huì)重新調(diào)用各個(gè)生命周期,切橫、豎屏?xí)r只會(huì)執(zhí)行一次

  • 設(shè)置 Activityandroid:configChanges="orientation|keyboardHidden" 時(shí),切屏不會(huì)重新調(diào)用各個(gè)生命周期,只會(huì)執(zhí)行 onConfigurationChanged 方法

  • 注意:還有一點(diǎn),非常重要,一個(gè) Android 的變更細(xì)節(jié)!當(dāng) API >12 時(shí),需要加入 screenSize 屬性,否則屏幕切換時(shí)即使你設(shè)置了 orientation 系統(tǒng)也會(huì)重建 Activity

  • 橫豎屏切換生命周期的執(zhí)行

1.3 不同場(chǎng)景下 Activity 生命周期的變化過(guò)程

不同場(chǎng)景下Activity生命周期的變化過(guò)程
  • 啟動(dòng) ActivityonCreate() ---> onStart() ---> onResume()Activity 進(jìn)入運(yùn)行狀態(tài)。
  • 鎖屏?xí)r會(huì)執(zhí)行 onPause()onStop() , 而開(kāi)屏?xí)r則應(yīng)該執(zhí)行 onStart() onResume()
已啟動(dòng)的 Activity 生命周期的變化
  • Activity 退居后臺(tái): 當(dāng)前 Activity 轉(zhuǎn)到新的 Activity 界面或按 Home 鍵回到主屏: onPause() ---> onStop() ,進(jìn)入停滯狀態(tài)。
  • Activity 返回前臺(tái): onRestart() ---> onStart() ---> onResume() ,再次回到運(yùn)行狀態(tài)。
  • Activity 退居后臺(tái): 且系統(tǒng)內(nèi)存不足, 系統(tǒng)會(huì)殺死這個(gè)后臺(tái)狀態(tài)的 Activity ,若再次回到這個(gè) Activity ,則會(huì)走 onCreate() --> onStart() ---> onResume()

1.4 將一個(gè) Activity 設(shè)置成窗口的樣式

設(shè)置 Activity 成窗口樣式

只需要給我們的 Activity 配置如下屬性即可。
android:theme="@android:style/Theme.Dialog"

1.5 退出已調(diào)用多個(gè) Activity 的 Application

  • 通常情況用戶退出一個(gè) Activity 只需按返回鍵,我們寫(xiě)代碼想退出 activity 直接調(diào)用 finish() 方法就行。
退出調(diào)用多個(gè) Activity 的 Application
  • 發(fā)送特定廣播:
  1. 在需要結(jié)束應(yīng)用時(shí), 發(fā)送一個(gè)特定的廣播,每個(gè) Activity 收到廣播后,關(guān)閉 即可。
  2. 給某個(gè) activity 注冊(cè)接受接受廣播的意圖 registerReceiver(receiver, filter)
  3. 如果過(guò)接受到的是 關(guān)閉 activity 的廣播 activity finish()
  • 遞歸退出
  1. 就調(diào)用 finish() 方法 把當(dāng)前的 Activity 退出
  2. 在打開(kāi)新的 Activity 時(shí)使用 startActivityForResult , 然后自己加標(biāo)志, 在 onActivityResult 中處理, 遞歸關(guān)閉。
  • 其實(shí)
  1. 也可以通過(guò) intentflag 來(lái)實(shí)現(xiàn) intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) 激活一個(gè)新的 activity
  2. 此時(shí)如果該任務(wù)棧中已經(jīng)有該 Activity , 那么系統(tǒng)會(huì)把這個(gè) Activity 上面的所有 Activity 干掉。
  3. 其實(shí)相當(dāng)于給 Activity 配置的啟動(dòng)模式為 singleTask
  • 記錄打開(kāi)的 Activity
  1. 每打開(kāi)一個(gè) Activity , 就記錄下來(lái)。
  2. 在需要退出時(shí) , 關(guān)閉每一個(gè) Activity

1.6 鎖定屏與解鎖屏幕,Activity 如何執(zhí)行生命周期

鎖定屏與解鎖屏幕,Activity如何執(zhí)行生命周期
  • 鎖屏?xí)r會(huì)執(zhí)行 onPause()onStop() , 而開(kāi)屏?xí)r則應(yīng)該執(zhí)行 onStart() onResume()

1.7 修改 Activity 進(jìn)入和退出動(dòng)畫(huà)

修改 Activity 進(jìn)入和退出動(dòng)畫(huà)
  • 可以通過(guò)兩種方式 , 一是通過(guò)定義 Activity 的主題 ,二是通過(guò)覆寫(xiě) ActivityoverridePendingTransition 方法。
  • 通過(guò)設(shè)置主題樣式在 styles.xml 中編輯代碼 , 添加 themes.xml 文件:在 AndroidManifest.xml 中給指定的 Activity 指定 theme
  • 覆寫(xiě) overridePendingTransition 方法:overridePendingTransition(R.anim.fade, R.anim.hold);

1.8 Activity 的四種狀態(tài)

四種狀態(tài)
  • runnig :用戶可以點(diǎn)擊,activity 處于棧頂狀態(tài)。
  • pausedactivity 失去焦點(diǎn)的時(shí)候,被一個(gè)非全屏的 activity 占據(jù)或者被一個(gè)透明的 activity 覆蓋,這個(gè)狀態(tài)的 activity 并沒(méi)有銷毀,它所有的狀態(tài)信息和成員變量仍然存在,只是不能夠被點(diǎn)擊。(內(nèi)存緊張的情況,這個(gè) activity 有可能被回收)
關(guān)閉
  • stopped :這個(gè) activity 被另外一個(gè) activity 完全覆蓋,但是這個(gè) activity 的所有狀態(tài)信息和成員變量仍然存在(除了內(nèi)存緊張)
  • killed :這個(gè) activity 已經(jīng)被銷毀,其所有的狀態(tài)信息和成員變量已經(jīng)不存在了。

1.9 如何處理異常退出

如何處理異常退出
  • Activity 異常退出的時(shí)候 --> onPause() --> onSaveInstanceState() --> onStop() --> onDestory()
  • 需要注意的是 onSaveInstanceState() 方法與 onPause 并沒(méi)有嚴(yán)格的先后關(guān)系,有可能在 onPause 之前,也有可能在其后面調(diào)用,但會(huì)在 onStop() 方法之前調(diào)用
  • 異常退出后又重新啟動(dòng)該 Activity --> onCreate() --> onStart() --> onRestoreInstanceState() --> onResume()
異常退出后又重新啟動(dòng)
  • 搞懂這個(gè)生命周期的執(zhí)行后就可以回答了,首先要知道面試官的意思:是要重新啟動(dòng)并恢復(fù)這個(gè) Activity 還是說(shuō)直接退出整個(gè) app
  • 如果要恢復(fù)則要在 onSaveInstanceState() 中進(jìn)行保存數(shù)據(jù)并在 onRestoreInstanceState() 中進(jìn)行恢復(fù)
  • 如果是要退出 app 的話就要捕獲全局的異常信息,并退出 app
  • 當(dāng)然個(gè)人建議是使用 UncaughtExceotionHandler 來(lái)捕獲全局異常進(jìn)行退出 app 的操作,這樣會(huì)減少之前崩潰所造成的后遺癥!

1.10 什么是 onNewIntent

onNewIntent
  • 如果 IntentActivity 處于任務(wù)棧的頂端,也就是說(shuō)之前打開(kāi)過(guò)的 Activity ,現(xiàn)在處于 onPauseonStop 狀態(tài)的話,其他應(yīng)用再發(fā)送 Intent 的話

  • 執(zhí)行順序?yàn)椋?code>onNewIntent,onRestartonStartonResume

二、 啟動(dòng)模式


2.1 啟動(dòng)模式

啟動(dòng)模式
  • Activity 一共有四種 launchModestandardsingleTopsingleTasksingleInstance
Standard
  • Standard 模式(默認(rèn)模式)
  1. 說(shuō)明: 每次啟動(dòng)一個(gè) Activity 都會(huì)又一次創(chuàng)建一個(gè)新的實(shí)例入棧,無(wú)論這個(gè)實(shí)例是否存在。

  2. 生命周期:每次被創(chuàng)建的實(shí)例 Activity 的生命周期符合典型情況,它的 onCreateonStartonResume 都會(huì)被調(diào)用。

  3. 舉例:此時(shí) Activity 棧中以此有 ABC 三個(gè) Activity ,此時(shí)C處于棧頂,啟動(dòng)模式為 Standard 模式。若在 C Activity 中加入點(diǎn)擊事件,須要跳轉(zhuǎn)到還有一個(gè)同類型的 C Activity 。結(jié)果是還有一個(gè) C Activity 進(jìn)入棧中,成為棧頂。

SingleTop
  • SingleTop 模式(棧頂復(fù)用模式)
  1. 說(shuō)明:分兩種處理情況:須要?jiǎng)?chuàng)建的 Activity 已經(jīng)處于棧頂時(shí),此時(shí)會(huì)直接復(fù)用棧頂?shù)?Activity 。不會(huì)再創(chuàng)建新的 Activity ;若須要?jiǎng)?chuàng)建的 Activity 不處于棧頂,此時(shí)會(huì)又一次創(chuàng)建一個(gè)新的 Activity 入棧,同 Standard 模式一樣。

  2. 生命周期:若情況一中棧頂?shù)?Activity 被直接復(fù)用時(shí),它的 onCreateonStart 不會(huì)被系統(tǒng)調(diào)用,由于它并沒(méi)有發(fā)生改變。可是一個(gè)新的方法 onNewIntent 會(huì)被回調(diào)( Activity 被正常創(chuàng)建時(shí)不會(huì)回調(diào)此方法)。

  3. 舉例:此時(shí) Activity 棧中以此有 ABC 三個(gè) Activity ,此時(shí) C 處于棧頂,啟動(dòng)模式為 SingleTop 模式。情況一:在 C Activity 中加入點(diǎn)擊事件,須要跳轉(zhuǎn)到還有一個(gè)同類型的 C Activity 。結(jié)果是直接復(fù)用棧頂?shù)?C Activity。情況二:在 C Activity 中加入點(diǎn)擊事件,須要跳轉(zhuǎn)到還有一個(gè) A Activity。結(jié)果是創(chuàng)建一個(gè)新的 Activity 入棧。成為棧頂。

SingleTask
  • SingleTask 模式(棧內(nèi)復(fù)用模式)
  1. 說(shuō)明:若須要?jiǎng)?chuàng)建的 Activity 已經(jīng)處于棧中時(shí),此時(shí)不會(huì)創(chuàng)建新的 Activity ,而是將存在棧中的 Activity 上面的其他 Activity 所有銷毀,使它成為棧頂。

  2. 如果是在別的應(yīng)用程序中啟動(dòng)它,則會(huì)新建一個(gè) task ,并在該task中啟動(dòng)這個(gè) ActivitysingleTask 允許別的 Activity 與其在一個(gè) task 中共存,也就是說(shuō),如果我在這個(gè) singleTask 的實(shí)例中再打開(kāi)新的 Activity ,這個(gè)新的 Activity 還是會(huì)在 singleTask 的實(shí)例的 task 中。

  3. 生命周期:同 SingleTop 模式中的情況一同樣。僅僅會(huì)又一次回調(diào) Activity 中的 onNewIntent 方法

  4. 舉例:此時(shí) Activity 棧中以此有 ABC 三個(gè) Activity 。此時(shí) C 處于棧頂,啟動(dòng)模式為 SingleTask 模式。情況一:在 C Activity 中加入點(diǎn)擊事件,須要跳轉(zhuǎn)到還有一個(gè)同類型的 C Activity 。結(jié)果是直接用棧頂?shù)?C Activity 。情況二:在 C Activity 中加入點(diǎn)擊事件,須要跳轉(zhuǎn)到還有一個(gè) A Activity 。結(jié)果是將 A Activity 上面的 BC 所有銷毀,使 A Activity 成為棧頂。

ingleInstance
  • SingleInstance 模式(單實(shí)例模式)
  1. 說(shuō)明: SingleInstance 比較特殊,是全局單例模式,是一種加強(qiáng)的 SingleTask 模式。它除了具有它所有特性外,還加強(qiáng)了一點(diǎn):只有一個(gè)實(shí)例,并且這個(gè)實(shí)例獨(dú)立運(yùn)行在一個(gè) task 中,這個(gè) task 只有這個(gè)實(shí)例,不允許有別的 Activity 存在。

  2. 這個(gè)經(jīng)常使用于系統(tǒng)中的應(yīng)用,比如 Launch 、鎖屏鍵的應(yīng)用等等,整個(gè)系統(tǒng)中僅僅有一個(gè)!所以在我們的應(yīng)用中一般不會(huì)用到。了解就可以。

  3. 舉例:比方 A Activity 是該模式,啟動(dòng) A 后。系統(tǒng)會(huì)為它創(chuàng)建一個(gè)單獨(dú)的任務(wù)棧,由于棧內(nèi)復(fù)用的特性。興許的請(qǐng)求均不會(huì)創(chuàng)建新的 Activity ,除非這個(gè)獨(dú)特的任務(wù)棧被系統(tǒng)銷毀。

2.2 啟動(dòng)模式的使用方式

啟動(dòng)模式的使用方式
  • Manifest.xml 中指定 Activity 啟動(dòng)模式
  1. 一種靜態(tài)的指定方法
  2. Manifest.xml 文件里聲明 Activity 的同一時(shí)候指定它的啟動(dòng)模式
  3. 這樣在代碼中跳轉(zhuǎn)時(shí)會(huì)依照指定的模式來(lái)創(chuàng)建 Activity
  • 啟動(dòng) Activity 時(shí)。在 Intent 中指定啟動(dòng)模式去創(chuàng)建 Activity
  1. 一種動(dòng)態(tài)的啟動(dòng)模式
  2. new 一個(gè) Intent
  3. 通過(guò) IntentaddFlags 方法去動(dòng)態(tài)指定一個(gè)啟動(dòng)模式。
  • 注意:以上兩種方式都能夠?yàn)?Activity 指定啟動(dòng)模式,可是二者還是有差別的。
  1. 優(yōu)先級(jí):動(dòng)態(tài)指定方式即另外一種比第一種優(yōu)先級(jí)要高,若兩者同一時(shí)候存在,以另外一種方式為準(zhǔn)。

  2. 限定范圍:第一種方式無(wú)法為 Activity 直接指定 FLAG_ACTIVITY_CLEAR_TOP 標(biāo)識(shí),另外一種方式無(wú)法為 Activity 指定 singleInstance 模式。

2.3 啟動(dòng)模式的實(shí)際應(yīng)用場(chǎng)景

這四種模式中的 Standard 模式是最普通的一種,沒(méi)有什么特別注意。而 SingleInstance 模式是整個(gè)系統(tǒng)的單例模式,在我們的應(yīng)用中一般不會(huì)應(yīng)用到。所以,這里就具體解說(shuō) SingleTopSingleTask 模式的運(yùn)用場(chǎng)景:

啟動(dòng)模式的實(shí)際應(yīng)用場(chǎng)景
  • SingleTask 模式的運(yùn)用場(chǎng)景
  1. 最常見(jiàn)的應(yīng)用場(chǎng)景就是保持我們應(yīng)用開(kāi)啟后僅僅有一個(gè) Activity 的實(shí)例。
  2. 最典型的樣例就是應(yīng)用中展示的主頁(yè)( Home 頁(yè))。
  3. 假設(shè)用戶在主頁(yè)跳轉(zhuǎn)到其他頁(yè)面,運(yùn)行多次操作后想返回到主頁(yè),假設(shè)不使用 SingleTask 模式,在點(diǎn)擊返回的過(guò)程中會(huì)多次看到主頁(yè),這明顯就是設(shè)計(jì)不合理了。
  • SingleTop 模式的運(yùn)用場(chǎng)景
  1. 假設(shè)你在當(dāng)前的 Activity 中又要啟動(dòng)同類型的 Activity
  2. 此時(shí)建議將此類型 Activity 的啟動(dòng)模式指定為 SingleTop ,能夠降低Activity的創(chuàng)建,節(jié)省內(nèi)存!
  • 注意:復(fù)用 Activity 時(shí)的生命周期回調(diào)
  1. 這里還須要考慮一個(gè) Activity 跳轉(zhuǎn)時(shí)攜帶頁(yè)面參數(shù)的問(wèn)題。
  2. 由于當(dāng)一個(gè) Activity 設(shè)置了 SingleTop 或者 SingleTask 模式后,跳轉(zhuǎn)此 Activity 出現(xiàn)復(fù)用原有 Activity 的情況時(shí),此 ActivityonCreate 方法將不會(huì)再次運(yùn)行。onCreate 方法僅僅會(huì)在第一次創(chuàng)建 Activity 時(shí)被運(yùn)行。
  3. 而一般 onCreate 方法中會(huì)進(jìn)行該頁(yè)面的數(shù)據(jù)初始化、UI 初始化,假設(shè)頁(yè)面的展示數(shù)據(jù)無(wú)關(guān)頁(yè)面跳轉(zhuǎn)傳遞的參數(shù),則不必操心此問(wèn)題
  4. 若頁(yè)面展示的數(shù)據(jù)就是通過(guò) getInten() 方法來(lái)獲取,那么問(wèn)題就會(huì)出現(xiàn):getInten() 獲取的一直都是老數(shù)據(jù),根本無(wú)法接收跳轉(zhuǎn)時(shí)傳送的新數(shù)據(jù)!
  • 以下,通過(guò)一個(gè)樣例來(lái)具體解釋:
圖片描述
  • 以上代碼中的 CourseDetailActivity 在配置文件里設(shè)置了啟動(dòng)模式是 SingleTop 模式,依據(jù)上面啟動(dòng)模式的介紹可得知,當(dāng) CourseDetailActivity 處于棧頂時(shí)。

  • 再次跳轉(zhuǎn)頁(yè)面到 CourseDetailActivity 時(shí)會(huì)直接復(fù)用原有的 Activity ,并且此頁(yè)面須要展示的數(shù)據(jù)是從 getIntent() 方法得來(lái),可是 initData() 方法不會(huì)再次被調(diào)用,此時(shí)頁(yè)面就無(wú)法顯示新的數(shù)據(jù)。

  • 當(dāng)然這樣的情況系統(tǒng)早就為我們想過(guò)了,這時(shí)我們須要另外一個(gè)回調(diào) onNewIntent(Intent intent)方法。此方法會(huì)傳入最新的 intent ,這樣我們就能夠解決上述問(wèn)題。這里建議的方法是又一次去 setIntent 。然后又一次去初始化數(shù)據(jù)和 UI 。代碼例如以下所看到的:

圖片描述
  • 這樣,在一個(gè)頁(yè)面中能夠反復(fù)跳轉(zhuǎn)并顯示不同的內(nèi)容。

2.4 快速啟動(dòng)一個(gè) Activity

快速啟動(dòng)一個(gè) Activity
  • 這個(gè)問(wèn)題其實(shí)也是比較簡(jiǎn)單的,就是不要在 ActivityonCreate 方法中執(zhí)行過(guò)多繁重的操作,并且在 onPasue 方法中同樣不能做過(guò)多的耗時(shí)操作。

2.5 啟動(dòng)流程

2.6 Activity 的 Flags

Activity 的 Flags
  • 標(biāo)記位既能夠設(shè)定Activity的啟動(dòng)模式,如同上面介紹的,在動(dòng)態(tài)指定啟動(dòng)模式,比方 FLAG_ACTIVITY_NEW_TASKFLAG_ACTIVITY_SINGLE_TOP 等。它還能夠影響 Activity 的運(yùn)行狀態(tài) ,比方 FLAG_ACTIVITY_CLEAN_TOPFLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 等。

  • 以下介紹幾個(gè)基本的標(biāo)記位,切勿死記,理解幾個(gè)就可以,須要時(shí)再查官方文檔。

幾個(gè)基本的標(biāo)記位
  • FLAG_ACTIVITY_NEW_TASK
  1. 作用是為 Activity 指定 “SingleTask” 啟動(dòng)模式。跟在 AndroidMainfest.xml 指定效果同樣
  • FLAG_ACTIVITY_SINGLE_TOP
  1. 作用是為 Activity 指定 “SingleTop” 啟動(dòng)模式,跟在 AndroidMainfest.xml 指定效果同樣。
  • FLAG_ACTIVITY_CLEAN_TOP
  1. 具有此標(biāo)記位的 Activity ,啟動(dòng)時(shí)會(huì)將與該 Activity 在同一任務(wù)棧的其他 Activity 出棧。
  2. 一般與 SingleTask 啟動(dòng)模式一起出現(xiàn)。
  3. 它會(huì)完畢 SingleTask 的作用。
  4. 但事實(shí)上 SingleTask 啟動(dòng)模式默認(rèn)具有此標(biāo)記位的作用
  • FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
  1. 具有此標(biāo)記位的 Activity 不會(huì)出如今歷史 Activity 的列表中
  2. 使用場(chǎng)景:當(dāng)某些情況下我們不希望用戶通過(guò)歷史列表回到 Activity 時(shí),此標(biāo)記位便體現(xiàn)了它的效果。
  3. 它等同于在 xml 中指定 Activity 的屬性.

2.7 onNewInstent()方法什么時(shí)候執(zhí)行

onNewInstent()方法什么時(shí)候執(zhí)行

這個(gè)是啟動(dòng)模式中的了,當(dāng)此 Activity 的實(shí)例已經(jīng)存在,并且此時(shí)的啟動(dòng)模式為 SingleTaskSingleInstance ,另外當(dāng)這個(gè)實(shí)例位于棧頂且啟動(dòng)模式為 SingleTop 時(shí)也會(huì)觸發(fā) onNewInstent()

三、 數(shù)據(jù)


3.1 Activity 間通過(guò) Intent 傳遞數(shù)據(jù)大小限制

Activity 間通過(guò) Intent 傳遞數(shù)據(jù)大小限制
  • Intent 在傳遞數(shù)據(jù)時(shí)是有大小限制的,這里官方并未詳細(xì)說(shuō)明,不過(guò)通過(guò)實(shí)驗(yàn)的方法可以測(cè)出數(shù)據(jù)應(yīng)該被限制在 1MB 之內(nèi)( 1024KB
  • 我們采用傳遞 Bitmap 的方法,發(fā)現(xiàn)當(dāng)圖片大小超過(guò) 1024(準(zhǔn)確地說(shuō)是 1020 左右)的時(shí)候,程序就會(huì)出現(xiàn)閃退、停止運(yùn)行等異常(不同的手機(jī)反應(yīng)不同)
  • 因此可以判斷 Intent 的傳輸容量在 1MB 之內(nèi)。

3.2 內(nèi)存不足時(shí)系統(tǒng)會(huì)殺掉后臺(tái)的Activity,若需要進(jìn)行一些臨時(shí)狀態(tài)的保存,在哪個(gè)方法進(jìn)行

onSaveInstanceState()
  • ActivityonSaveInstanceState()onRestoreInstanceState() 并不是生命周期方法,它們不同于 onCreate()onPause() 等生命周期方法,它們并不一定會(huì)被觸發(fā)。

  • onSaveInstanceState() 方法,當(dāng)應(yīng)用遇到意外情況(如:內(nèi)存不足、用戶直接按 Home 鍵)由系統(tǒng)銷毀一個(gè) ActivityonSaveInstanceState() 會(huì)被調(diào)用。

  • 但是當(dāng)用戶主動(dòng)去銷毀一個(gè) Activity 時(shí),例如在應(yīng)用中按返回鍵,onSaveInstanceState() 就不會(huì)被調(diào)用。

  • 除非該 activity 不是被用戶主動(dòng)銷毀的,通常 onSaveInstanceState() 只適合用于保存一些臨時(shí)性的狀態(tài),而 onPause() 適合用于數(shù)據(jù)的持久化保存。

3.3 onSaveInstanceState() 被執(zhí)行的場(chǎng)景

onSaveInstanceState() 被執(zhí)行的場(chǎng)景
  • 系統(tǒng)不知道你按下 HOME 后要運(yùn)行多少其他的程序,自然也不知道 activity A 是否會(huì)被銷毀
  • 因此系統(tǒng)都會(huì)調(diào)用 onSaveInstanceState() ,讓用戶有機(jī)會(huì)保存某些非永久性的數(shù)據(jù)。以下幾種情況的分析都遵循該原則:
  1. 當(dāng)用戶按下 HOME 鍵時(shí)
  2. 長(zhǎng)按 HOME 鍵,選擇運(yùn)行其他的程序時(shí)
  3. 鎖屏?xí)r
  4. activity A 中啟動(dòng)一個(gè)新的 activity 時(shí)
  5. 屏幕方向切換時(shí)

3.4 兩個(gè) Activity 之間跳轉(zhuǎn)時(shí)必然會(huì)執(zhí)行的方法

兩個(gè) Activity 之間跳轉(zhuǎn)時(shí)必然會(huì)執(zhí)行的方法

一般情況下比如說(shuō)有兩個(gè) activity , 分別叫 A , B ,當(dāng)在 A 里面激活 B 組件的時(shí)候, A 會(huì)調(diào)用 onPause() 方法,然后 B 調(diào)用 onCreate() , onStart() , onResume()

這個(gè)時(shí)候 B 覆蓋了窗體, A 會(huì)調(diào)用 onStop() 方法. 如果 B 是個(gè)透明的,或者 是對(duì)話框的樣式, 就不會(huì)調(diào)用 AonStop() 方法。

3.5 用 Intent 去啟動(dòng)一個(gè)Activity 之外的方法

用 Intent 去啟動(dòng)一個(gè)Activity 之外的方法
  • 使用 adb shell am 命令
  1. am 啟動(dòng)一個(gè) activity
  2. adb shell am start com.example.fuchenxuan/.MainActivity
  3. am 發(fā)送一個(gè)廣播,使用 action
  4. adb shell am broadcast -a magcomm.action.TOUCH_LETTER

3.6 scheme 跳轉(zhuǎn)協(xié)議

scheme跳轉(zhuǎn)協(xié)議

3.6.1 定義

定義
  • 服務(wù)器可以定制化跳轉(zhuǎn) app 頁(yè)面

  • app 可以通過(guò) Scheme 跳轉(zhuǎn)到另一個(gè) app 頁(yè)面

  • 可以通過(guò) h5 頁(yè)面跳轉(zhuǎn) app 原生頁(yè)面

3.6.2 協(xié)議格式:

協(xié)議格式
協(xié)議格式
  • qh 代表 Scheme 協(xié)議名稱

  • test 代表 Scheme 作用的地址域

  • 8080 代表改路徑的端口號(hào)

  • /goods 代表的是指定頁(yè)面(路徑)

  • goodsIdname 代表傳遞的兩個(gè)參數(shù)

3.6.3 Scheme使用

  • 定義一個(gè) Scheme
image
  • 獲取 Scheme 跳轉(zhuǎn)的參數(shù)
image
  • 調(diào)用方式
  1. 原生調(diào)用
image
  1. html調(diào)用
image
  1. 判斷某個(gè)Scheme是否有效
image


四、 Context


4.1 Context , Activity , Appliction 的區(qū)別

Context, Activity, Appliction 的區(qū)別
  • 相同:ActivityApplication 都是 Context 的子類。
  • Context 從字面上理解就是上下文的意思, 在實(shí)際應(yīng)用中它也確實(shí)是起到了管理 上下文環(huán)境中各個(gè)參數(shù)和變量的總用, 方便我們可以簡(jiǎn)單的訪問(wèn)到各種資源。
  • 不同:維護(hù)的生命周期不同。Context 維護(hù)的是當(dāng)前的 Activity 的生命周期, Application 維護(hù)的是整個(gè)項(xiàng)目的生命周期。
  • 使用 context 的時(shí)候, 小心內(nèi)存泄露, 防止內(nèi)存泄露

4.2 Context 是什么

Context 是什么
  • 它描述的是一個(gè)應(yīng)用程序環(huán)境的信息,即上下文。

  • 該類是一個(gè)抽象( abstract class )類, Android 提供了該抽象類的具體實(shí) 現(xiàn)類( ContextIml )。

  • 通過(guò)它我們可以獲取應(yīng)用程序的資源和類, 也包括一些應(yīng)用級(jí)別操作, 例如:啟動(dòng)一個(gè) Activity ,發(fā)送廣播,接受 Intent ,信息,等。

4.2.1 附加一張 Context 繼承關(guān)系圖

[圖片上傳失敗...(image-de33df-1572405738902)]

4.3 獲取當(dāng)前屏幕 Activity 的對(duì)象

獲取當(dāng)前屏幕Activity的對(duì)象

4.4 Activity 的管理機(jī)制

Activity的管理機(jī)制
  1. 什么是 ActivityRecord
  2. 什么是 TaskRecord
  3. 什么是 ActivityManagerService

4.5 什么是 Activity

什么是 Activity
  • 四大組件之一,通常一個(gè)用戶交互界面對(duì)應(yīng)一個(gè) activity
  • activityContext 的子類,同時(shí)實(shí)現(xiàn)了 window.callbackkeyevent.callback ,可以處理與窗體用戶交互的事件。
  • 開(kāi)發(fā)中常用的有 FragmentActivityListActivityTabActivityAndroid 4.0Fragment 取代)

五、 進(jìn)程


5.1 Android 進(jìn)程優(yōu)先級(jí)

  • 前臺(tái) / 可見(jiàn) / 服務(wù) / 后臺(tái) / 空
前臺(tái) / 可見(jiàn) / 服務(wù) / 后臺(tái) / 空

5.1.1 前臺(tái)進(jìn)程:Foreground process

前臺(tái)進(jìn)程:Foreground process
  • 用戶正在交互的 ActivityonResume()
  • 當(dāng)某個(gè) Service 綁定正在交互的 Activity
  • 被主動(dòng)調(diào)用為前臺(tái) ServicestartForeground()
  • 組件正在執(zhí)行生命周期的回調(diào)( onCreate()onStart()onDestory()
  • BroadcastReceiver 正在執(zhí)行 onReceive()

5.1.2 可見(jiàn)進(jìn)程:Visible process

可見(jiàn)進(jìn)程:Visible process
  • 我們的 Activity 處在 onPause()(沒(méi)有進(jìn)入 onStop()
  • 綁定到前臺(tái) ActivityService

5.1.3 服務(wù)進(jìn)程:Service process

服務(wù)進(jìn)程
  • 簡(jiǎn)單的 startService() 啟動(dòng)。

5.1.4 后臺(tái)進(jìn)程:Background process

后臺(tái)進(jìn)程:Background process
  • 對(duì)用戶沒(méi)有直接影響的進(jìn)程 --- Activity 處于 onStop() 的時(shí)候。
  • android:process=":xxx"

5.1.5 空進(jìn)程:Empty process

空進(jìn)程:Empty process
  • 不含有任何的活動(dòng)的組件。( Android 設(shè)計(jì)的,處于緩存的目的,為了第二次啟動(dòng)更快,采取的一個(gè)權(quán)衡)

5.2 可見(jiàn)進(jìn)程

可見(jiàn)進(jìn)程

可見(jiàn)進(jìn)程指部分程序界面能夠被用戶看見(jiàn),卻不在前臺(tái)與用戶交互的進(jìn)程。例如,我們?cè)谝粋€(gè)界面上彈出一個(gè)對(duì)話框(該對(duì)話框是一個(gè)新的 Activity ),那么在對(duì)話框后面的原界面是可見(jiàn)的,但是并沒(méi)有與用戶進(jìn)行交互,那么原界面就是可見(jiàn)進(jìn)程。

  • 一個(gè)進(jìn)程滿足下面任何一個(gè)條件都被認(rèn)為是可視的:
  1. 寄宿著一個(gè)不是前臺(tái)的活動(dòng),但是它對(duì)用戶仍可見(jiàn)(它的 onPause() 方法已經(jīng)被調(diào)用)。舉例來(lái)說(shuō),這可能發(fā)生在,如果一個(gè)前臺(tái)活動(dòng)在一個(gè)對(duì)話框(其他進(jìn)程的)運(yùn)行之后仍然是可視的,比如輸入法的彈出時(shí)。
  2. 寄宿著一個(gè)服務(wù),該服務(wù)綁定到一個(gè)可視的活動(dòng)。
  • 一個(gè)可視進(jìn)程被認(rèn)為是及其重要的且不會(huì)被殺死,除非為了保持前臺(tái)進(jìn)程運(yùn)行。

5.3 服務(wù)進(jìn)程

服務(wù)進(jìn)程
  • 服務(wù)進(jìn)程是通過(guò) startService() 方法啟動(dòng)的進(jìn)程,但不屬于前臺(tái)進(jìn)程和可見(jiàn)進(jìn)程。例如,在后臺(tái)播放音樂(lè)或者在后臺(tái)下載就是服務(wù)進(jìn)程。

  • 系統(tǒng)保持它們運(yùn)行,除非沒(méi)有足夠內(nèi)存來(lái)保證所有的前臺(tái)進(jìn)程和可視進(jìn)程。

5.4 后臺(tái)進(jìn)程

后臺(tái)進(jìn)程
  • 后臺(tái)進(jìn)程是一個(gè)保持著一個(gè)當(dāng)前對(duì)用戶不可視的活動(dòng)(已經(jīng)調(diào)用 Activity 對(duì)象的 onStop() 方法)(如果還有除了 UI 線程外其他線程在運(yùn)行話,不受影響)。

例如我正在使用 qq 和別人聊天,這個(gè)時(shí)候 qq 是前臺(tái)進(jìn)程,但是當(dāng)我點(diǎn)擊 Home 鍵讓 qq 界面消失的時(shí)候,這個(gè)時(shí)候它就轉(zhuǎn)換成了后臺(tái)進(jìn)程。

  • 這些進(jìn)程沒(méi)有直接影響用戶體驗(yàn),并且可以在任何時(shí)候被殺以收回內(nèi)存用于一個(gè)前臺(tái)、可視、服務(wù)進(jìn)程。
  • 一般地有很多后臺(tái)進(jìn)程運(yùn)行著,因此它們保持在一個(gè) LRUleast recently used ,即最近最少使用,如果您學(xué)過(guò)操作系統(tǒng)的話會(huì)覺(jué)得它很熟悉,跟內(nèi)存的頁(yè)面置換算法 LRU 一樣)列表以確保最近使用最多的活動(dòng)的進(jìn)程最后被殺。

5.5 空進(jìn)程

空進(jìn)程
  • 空進(jìn)程是一個(gè)沒(méi)有保持活躍的應(yīng)用程序組件的進(jìn)程,不包含任何活躍組件。

  • 保持這個(gè)進(jìn)程可用的唯一原因是作為一個(gè) cache 以提高下次啟動(dòng)組件的速度。系統(tǒng)進(jìn)程殺死這些進(jìn)程,以在進(jìn)程 cache 和潛在的內(nèi)核 cache 之間平衡整個(gè)系統(tǒng)資源。

  • android 進(jìn)程的回收順序從先到后分別是:空進(jìn)程,后臺(tái)進(jìn)程,服務(wù)進(jìn)程,可見(jiàn)進(jìn)程,前臺(tái)進(jìn)程。

5.6 什么是 ANR,如何避免

什么是 ANR,如何避免

5.6.1 什么是ANR

什么是ANR
  • ANR ,全稱為 Application Not Responding
  • Android 中,如果你的應(yīng)用程序有一段時(shí)間沒(méi)有響應(yīng),系統(tǒng)會(huì)向用戶顯示一個(gè)對(duì)話框,這個(gè)對(duì)話框稱作應(yīng)用程序無(wú)響應(yīng)對(duì)話框。

5.6.2 用戶行為

用戶行為
  • 用戶可以選擇讓程序繼續(xù)運(yùn)行,也可以讓程序停止運(yùn)行。
  • 他們?cè)谑褂媚愕膽?yīng)用程序時(shí),并不希望每次都要處理這個(gè)對(duì)話框。
  • 因此,在程序里對(duì)響應(yīng)性能的設(shè)計(jì)很重要,這樣,系統(tǒng)不會(huì)顯示 ANR 給用戶。

5.6.3 Android不同組件ANR超時(shí)時(shí)間不同

Android不同組件ANR超時(shí)時(shí)間不同
  • 不同的組件發(fā)生 ANR 的時(shí)間不一樣,主線程( ActivityService )是 5 秒,BroadCastReceiver10 秒。

5.6.4 解決方案

解決方案
  1. 將所有耗時(shí)操作,比如訪問(wèn)網(wǎng)絡(luò),Socket 通信,查詢大量 SQL 語(yǔ)句,復(fù)雜邏輯計(jì)算等都放在子線程中去,然后通過(guò) handler.sendMessagerunonUITreadAsyncTask 等方式更新 UI ,以確保用戶界面操作的流暢度。
  2. 如果耗時(shí)操作需要讓用戶等待,那么可以在界面上顯示進(jìn)度條。

5.7 android的任務(wù)棧 Task

android的任務(wù)棧 Task
  • 一個(gè) Task 包含的就是 activity 集合,android 系統(tǒng)可以通過(guò)任務(wù)棧有序的管理 activity
  • 一個(gè)app當(dāng)中可能不止一個(gè)任務(wù)棧,在某些情況下,一個(gè) activity 也可以獨(dú)享一個(gè)任務(wù)棧( singleInstance 模式啟動(dòng)的 activity

總結(jié)


  1. 本文基本涵蓋了 Android Activity 的所有知識(shí)點(diǎn)。對(duì)于 App 啟動(dòng)、AMS 希望大家能根據(jù)文中鏈接或者 Google 搜索的形式繼續(xù)展開(kāi)學(xué)習(xí)。
  2. 重點(diǎn):關(guān)于 Android 的四大組件,到現(xiàn)在為止我才總結(jié)完 Activity ,馬上我將繼續(xù)針對(duì),ServiceBroadcastRecevier 等,以及事件分發(fā)、滑動(dòng)沖突、新能優(yōu)化等重要模塊,進(jìn)行全面總結(jié),歡迎大家關(guān)注 _yuanhao 的 簡(jiǎn)書(shū) ,方便及時(shí)接收更新

碼字不易,你的點(diǎn)贊是我總結(jié)的最大動(dòng)力!


Android
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,963評(píng)論 6 542
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,348評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 178,083評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 63,706評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,442評(píng)論 6 412
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,802評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,795評(píng)論 3 446
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,983評(píng)論 0 290
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,542評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,287評(píng)論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,486評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,030評(píng)論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,710評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 35,116評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 36,412評(píng)論 1 294
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,224評(píng)論 3 398
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,462評(píng)論 2 378