1.1 請(qǐng)簡(jiǎn)要談?wù)凙ndroid系統(tǒng)的架構(gòu)組成驻仅?
android系統(tǒng)分為四部分黑低,從高到低分別是:
1责蝠、Android應(yīng)用層
Android會(huì)同一系列核心應(yīng)用程序包一起發(fā)布俺附,該應(yīng)用程序包包括email客戶端浪蹂,SMS短消息程序抵栈,日歷,地圖坤次,瀏覽器古劲,聯(lián)系人管理程序等。所有的應(yīng)用程序都是使用JAVA語(yǔ)言編寫(xiě)的缰猴。
2产艾、Android應(yīng)用框架層
開(kāi)發(fā)人員也可以完全訪問(wèn)核心應(yīng)用程序所使用的API框架。該應(yīng)用程序的架構(gòu)設(shè)計(jì)簡(jiǎn)化了組件的重用;任何一個(gè)應(yīng)用程序都可以發(fā)布它的功能塊并且任何其它的應(yīng)用程序都可以使用其所發(fā)布的功能塊(不過(guò)得遵循框架的安全性限制)。同樣闷堡,該應(yīng)用程序重用機(jī)制也使用戶可以方便的替換程序組件隘膘。
3、Android系統(tǒng)運(yùn)行層
Android 包含一些C/C++庫(kù)缚窿,這些庫(kù)能被Android系統(tǒng)中不同的組件使用棘幸。它們通過(guò) Android 應(yīng)用程序框架為開(kāi)發(fā)者提供服務(wù)。
4倦零、Linux內(nèi)核層
Android 的核心系統(tǒng)服務(wù)依賴于 Linux 2.6 內(nèi)核误续,如安全性,內(nèi)存管理扫茅,進(jìn)程管理蹋嵌, 網(wǎng)絡(luò)協(xié)議棧和驅(qū)動(dòng)模型。
Linux 內(nèi)核也同時(shí)作為硬件和軟件棧之間的抽象層葫隙。
1.2 SharedPreferences 是線程安全的嗎栽烂?它的 commit 和 apply 方法有什么區(qū)別?
1.SharePreferences是線程安全的恋脚,里面的方法有大量的synchronized來(lái)保障
2.SharePreferences不是進(jìn)程安全的腺办,即使你用了MODE_MULTI_PROCESS
3.第一次getSharePreference會(huì)讀取磁盤(pán)文件,異步讀取糟描,寫(xiě)入到內(nèi)存中怀喉,后續(xù)的getSharePreference都是從內(nèi)存中拿了
4.第一次讀取完畢之前,所有的get/set請(qǐng)求都會(huì)被卡住船响,等待讀取完畢后再執(zhí)行躬拢,所以第一次讀取會(huì)有ANR風(fēng)險(xiǎn)
5.所有的get都是從內(nèi)存中讀取
6.提交都是寫(xiě)入到內(nèi)存和磁盤(pán)中,apply跟commit的區(qū)別在于apply是內(nèi)存同步见间,然后磁盤(pán)異步寫(xiě)入任務(wù)放到一個(gè)單線程隊(duì)列中等待調(diào)用聊闯,方法無(wú)返回,即void
commit內(nèi)存同步米诉,只不過(guò)要等待磁盤(pán)寫(xiě)入結(jié)束才返回菱蔬,直接返回寫(xiě)入成功狀態(tài) true or false
7.從 Android N 開(kāi)始, 不再支持 MODE_WORLD_READABLE & MODE_WORLD_WRITEABLE史侣, 一旦指定汗销,會(huì)拋異常 。也不要用MODE_MULTI_PROCESS 遲早被放棄抵窒。
8.每次commit/apply都會(huì)把全部數(shù)據(jù)一次性寫(xiě)入到磁盤(pán)弛针,即沒(méi)有增量寫(xiě)入的概念 。 所以單個(gè)文件千萬(wàn)不要太大 否則會(huì)嚴(yán)重影響性能李皇。
1.3 Serializable和Parcelable的區(qū)別?
Android中序列化有兩種方式:Serializable以及Parcelable削茁。其中Serializable是Java自帶的宙枷,而
Parcelable是安卓專(zhuān)有的。
Seralizable相對(duì)Parcelable而言茧跋,好處就是非常簡(jiǎn)單慰丛,只需對(duì)需要序列化的類(lèi)class執(zhí)行就可以,不需要手動(dòng)去處理序列化和反序列化的過(guò)程瘾杭,所以常常用于網(wǎng)絡(luò)請(qǐng)求數(shù)據(jù)處理诅病,Activity之間傳遞值的使用。
Parcelable是android特有的序列化API粥烁,它的出現(xiàn)是為了解決Serializable在序列化的過(guò)程中消耗資源嚴(yán)重的問(wèn)題贤笆,但是因?yàn)楸旧硎褂眯枰謩?dòng)處理序列化和反序列化過(guò)程,會(huì)與具體的代碼綁定讨阻,使用較為繁瑣芥永,一般只獲取內(nèi)存數(shù)據(jù)的時(shí)候使用。
1.4 請(qǐng)簡(jiǎn)述一下 Android 7.0 的新特性钝吮?
- 低電耗功能改進(jìn)
- 引入畫(huà)中畫(huà)功能
- 引入“長(zhǎng)按快捷方式”埋涧,即App Shortcuts
- 引入混合模式,同時(shí)存在解釋執(zhí)行/AOT/JIT奇瘦,安裝應(yīng)用時(shí)默認(rèn)不全量編譯棘催,使得安裝應(yīng)用時(shí)間大大縮短
- 引入了對(duì)私有平臺(tái)庫(kù)限制,然而用一個(gè)叫做Nougat_dlfunctions的庫(kù)就行
- 不推薦使用file:// URI傳遞數(shù)據(jù)耳标,轉(zhuǎn)而推薦使用FileProvider
- 快速回復(fù)通知
1.5 談?wù)凙rrayMap和HashMap的區(qū)別醇坝?
- 查找效率
HashMap因?yàn)槠涓鶕?jù)hashcode的值直接算出index,所以其查找效率是隨著數(shù)組長(zhǎng)度增大而增加的。
ArrayMap使用的是二分法查找麻捻,所以當(dāng)數(shù)組長(zhǎng)度每增加一倍時(shí)纲仍,就需要多進(jìn)行一次判斷呀袱,效率下降 - 擴(kuò)容數(shù)量
HashMap初始值16個(gè)長(zhǎng)度贸毕,每次擴(kuò)容的時(shí)候,直接申請(qǐng)雙倍的數(shù)組空間夜赵。
ArrayMap每次擴(kuò)容的時(shí)候明棍,如果size長(zhǎng)度大于8時(shí)申請(qǐng)size*1.5個(gè)長(zhǎng)度,大于4小于8時(shí)申請(qǐng)8個(gè)寇僧,小于4時(shí)申請(qǐng)4個(gè)摊腋。這樣比較ArrayMap其實(shí)是申請(qǐng)了更少的內(nèi)存空間,但是擴(kuò)容的頻率會(huì)更高嘁傀。因此兴蒸,如果數(shù)據(jù)量比較大的時(shí)候,還是使用HashMap更合適细办,因?yàn)槠鋽U(kuò)容的次數(shù)要比ArrayMap少很多橙凳。 - 擴(kuò)容效率
HashMap每次擴(kuò)容的時(shí)候重新計(jì)算每個(gè)數(shù)組成員的位置,然后放到新的位置。
ArrayMap則是直接使用System.arraycopy岛啸,所以效率上肯定是ArrayMap更占優(yōu)勢(shì)钓觉。 - 內(nèi)存消耗
以ArrayMap采用了一種獨(dú)特的方式,能夠重復(fù)的利用因?yàn)閿?shù)據(jù)擴(kuò)容而遺留下來(lái)的數(shù)組空間坚踩,方便下一個(gè)ArrayMap的使用荡灾。而HashMap沒(méi)有這種設(shè)計(jì)。 由于ArrayMap之緩存了長(zhǎng)度是4和8的時(shí)候瞬铸,所以如果頻繁的使用到Map批幌,而且數(shù)據(jù)量都比較小的時(shí)候,ArrayMap無(wú)疑是相當(dāng)?shù)氖枪?jié)省內(nèi)存的赴捞。 - 總結(jié)
綜上所述逼裆,數(shù)據(jù)量比較小,并且需要頻繁的使用Map存儲(chǔ)數(shù)據(jù)的時(shí)候赦政,推薦使用ArrayMap胜宇。 而數(shù)據(jù)量比較大的時(shí)候,則推薦使用HashMap恢着。
1.6 簡(jiǎn)要說(shuō)說(shuō) LruCache 的原理桐愉?
androidx.collection.LruCache初始化的時(shí)候, 會(huì)限制緩存占據(jù)內(nèi)存空間的總?cè)萘縨axSize;
底層維護(hù)的是 LinkedHashMap, 使用 LruCache 最好要重寫(xiě) sizeOf 方法, 用于計(jì)算每個(gè)被緩存的對(duì)象, 在內(nèi)存中存儲(chǔ)時(shí), 占用多少空間;
在 put 操作時(shí), 首先計(jì)算新的緩存對(duì)象, 占多少空間, 再根據(jù)key, 移除老的對(duì)象,占用內(nèi)存大小 = 之前占用的內(nèi)存大小 + 新對(duì)象的大小 - 老對(duì)象的大小;
put 操作最后總會(huì)根據(jù) maxSize, 在拿到LinkedHashMap.EntrySet 中鏈表的頭節(jié)點(diǎn), 循環(huán)判斷, 只要當(dāng)前緩存對(duì)象占據(jù)內(nèi)存超出 maxSize, 就移除一個(gè)頭節(jié)點(diǎn), 一直到符合要求;
lruCache 和 LinkedHashMap 的關(guān)系:
LinkedHashMap 中維護(hù)一個(gè)雙向鏈表, 并維護(hù) head 和tail 指針, lruCache 使用了 LinkedHashMap accessOrder為 true 的屬性, 只要訪問(wèn)了某個(gè) key,包括 get 和 put, 就把當(dāng)前這個(gè) entry 放在鏈表的尾節(jié)點(diǎn),所以鏈表的頭節(jié)點(diǎn), 是最老訪問(wèn)的節(jié)點(diǎn), 尾節(jié)點(diǎn)是最新訪問(wèn)的節(jié)點(diǎn),
所以, lruCache 就很巧妙的利用了這個(gè)特點(diǎn), 完成了 LeastRecently Used 的需求;
1.7 為什么推薦用SparseArray代替HashMap?
并不能替換所有的HashMap掰派。只能替換以int類(lèi)型為key的HashMap从诲。
HashMap中如果以int為key,會(huì)強(qiáng)制使用Integer這個(gè)包裝類(lèi)型靡羡,當(dāng)我們使用int類(lèi)型作為key的時(shí)候系統(tǒng)會(huì)自用裝箱成為Integer系洛,這個(gè)過(guò)程會(huì)創(chuàng)建對(duì)象一想效率。
SparseArray內(nèi)部是一個(gè)int數(shù)組和一個(gè)object數(shù)組略步∶璩叮可以直接使用int減少了自動(dòng)裝箱操作。
1.8 PathClassLoader和DexClassLoader有何區(qū)別趟薄?
根據(jù)art源碼來(lái)看绽诚,兩者都繼承自BaseDexClassLoader,最終都會(huì)創(chuàng)建一個(gè)DexFile杭煎,不同點(diǎn)是一個(gè)關(guān)鍵的參數(shù):
optimizedDirectory恩够,PathClassLoader為null,DexClassLoader則使用傳遞進(jìn)來(lái)的
然后會(huì)根據(jù)optimizedDirectory判斷對(duì)應(yīng)的oat文件是否已經(jīng)生成(null則使用/data/dalvik-cache/)羡铲,如果有且該oat對(duì)應(yīng)的dex正確則直接加載蜂桶,否則觸發(fā)dex2oat(就是這家伙耗了我們寶貴的時(shí)間!R睬小)扑媚,成功則用生成的oat妥曲,失敗則走解釋執(zhí)行
注意:貌似Q版做了優(yōu)化,不會(huì)再卡死在dex2oat里了,根據(jù)加載外部dex的實(shí)驗(yàn)钦购,DexClassLoader會(huì)觸發(fā)dex2oat檐盟,而PathClassLoader不會(huì)
1.9 說(shuō)說(shuō)HttpClient與HttpUrlConnection的區(qū)別?并談?wù)劄楹吻罢邥?huì)被替代押桃?
1葵萎,android2.3之前,HttpUrlConnection具有一些bug唱凯,例如關(guān)閉輸入流時(shí)可能導(dǎo)致連接池關(guān)閉羡忘。
2,android2.3之后磕昼,HttpUrlConnection才相對(duì)成熟卷雕。特點(diǎn)是,輕量票从、api少
3漫雕,HttpClient一直很強(qiáng)大,支持get峰鄙、post浸间、delete等其他協(xié)議。
具體可參考表格:[Android] HttpURLConnection & HttpClient & Socket
被替代原因:太重了吟榴,api太多魁蒜;針對(duì)Android系統(tǒng),不便于向后維護(hù)
1.10 什么是Lifecycle吩翻?請(qǐng)分析其內(nèi)部原理和使用場(chǎng)景兜看?
Jetpack 的 Lifecycle 庫(kù):它可以有效的避免內(nèi)存泄漏,解決 Android 生命周期的常見(jiàn)難題狭瞎。
內(nèi)部原理:ComponentActivity 的 onCreate 方法中注入了 ReportFragment细移,通過(guò) Fragment 來(lái)實(shí)現(xiàn)生命周期監(jiān)聽(tīng)。
使用場(chǎng)景:給 RecyclerView 的 ViewHolder 添加 Lifecycle的能力脚作。自己實(shí)現(xiàn) LifecycleHandler葫哗,在 Activity 銷(xiāo)毀的時(shí)候缔刹,自動(dòng)移除 Handler 的消息避免 Handler 導(dǎo)致的內(nèi)存泄漏球涛。
1.11 談一談Android的簽名機(jī)制?
當(dāng)面試題要考察你某個(gè)技術(shù)的理解時(shí)校镐,除了他們兩個(gè)在技術(shù)上的區(qū)別和特點(diǎn)之外亿扁。更希望聽(tīng)到的是在業(yè)務(wù)上的應(yīng)用,技術(shù)是為業(yè)務(wù)服務(wù)的鸟廓,展現(xiàn)你的業(yè)務(wù)能力遠(yuǎn)比展現(xiàn)你的技術(shù)能力要重要从祝。
現(xiàn)在我將從技術(shù)和業(yè)務(wù)應(yīng)用兩個(gè)方面來(lái)剖析android v1和v2簽名的區(qū)別襟己。
關(guān)于v1和v2兩種簽名的技術(shù)上的區(qū)別上面??已經(jīng)有很詳細(xì)的回答了,那么我就說(shuō)一說(shuō)他們?cè)跇I(yè)務(wù)應(yīng)用方面的區(qū)別:
我們有時(shí)候做app推廣牍陌,需要記錄這個(gè)APP是通過(guò)誰(shuí)的推廣鏈接安裝的擎浴,那么我我們只需要在每次通過(guò)服務(wù)器下發(fā)apk的時(shí)候?qū)pk文件動(dòng)一些手腳,在apk中標(biāo)示這個(gè)apk是哪個(gè)用戶分享的毒涧,然后當(dāng)apk安裝好打開(kāi)時(shí)就可以讀到apk事先存儲(chǔ)好的標(biāo)示,從而實(shí)現(xiàn)我們需要的業(yè)務(wù)需求贮预。
給apk文件動(dòng)手腳,v1支持契讲,v1+v2的簽名方式就不支持了仿吞。
1.12 談?wù)劙沧縜pk構(gòu)建的流程?
- 使用aapt處理資源文件捡偏,如編譯AndroidManifest.xml唤冈,編譯生成resources.arsc,生成R.java等
- 使用javac等工具編譯java文件银伟,生成class格式文件
- 使用dx等工具將.class和項(xiàng)目依賴的jar編譯成.dex
- 將生成的這些文件壓縮進(jìn)一個(gè)zip中
- 簽名
這只是最簡(jiǎn)單的過(guò)程你虹,實(shí)際還會(huì)涉及到multidex,使用如proguard的工具處理生成的字節(jié)碼彤避,需要依賴aar文件售葡,需要編譯kotlin,使用jack忠藤,使用jni挟伙,使用d8/r8等情況~
1.13 簡(jiǎn)述一下Android 8.0 至12.0 分別增加了哪些新特性?
Android 12.0
- 原生的ImageDecoder支持GIF和WebP格式
- 支持圓角模孩,Display.getRounderCorner()獲取屏幕圓角的詳細(xì)信息
- 更易用的模糊尖阔、色彩濾鏡等特效,View.setRenderEffect(RenderEffect) 將特效直接應(yīng)用于視圖
- 限制對(duì)MAC地址的訪問(wèn)
- 應(yīng)用覆蓋控制榨咐,可以控制是否允許在自己的內(nèi)容上顯示這些覆蓋圖層介却,調(diào)用Window#setHideOverlayWindows(),表明不允許TYPE_APPLICATION_OVERLAY的窗口顯示
- 應(yīng)用無(wú)法關(guān)閉系統(tǒng)對(duì)話框块茁,棄用了 ACTION_CLOSE_SYSTEM_DIALOGS intent 操作
- Activity/BroadcastReciver/Service 聲明了Filter齿坷,則必須顯示設(shè)置android:exported屬性
- 必須為每個(gè)PendingIntent設(shè)置可變性
- 后臺(tái)應(yīng)用無(wú)法再啟動(dòng)前臺(tái)服務(wù)
Android 11.0
- 短信更新改進(jìn),提供更加友好的交互
- 權(quán)限和隱私数焊,在Android10的用戶隱私基礎(chǔ)上永淌,新增了位置、麥克風(fēng)和攝像頭的一次性權(quán)限許可
- 內(nèi)置屏幕錄制
- 適配不同設(shè)備佩耳,折疊屏支持優(yōu)化遂蛀,增加鉸鏈角度傳感器API等;高刷新率支持
- 網(wǎng)絡(luò)優(yōu)化干厚,新增『動(dòng)態(tài)計(jì)量API』李滴,如果檢測(cè)到連接到無(wú)限5G信號(hào)螃宙,將可以訪問(wèn)最高質(zhì)量的視頻和圖片
Android 10.0
- 5G支持
- 支持可折疊設(shè)備
- 暗黑主題
- 手勢(shì)導(dǎo)航,全面屏手勢(shì)操作
- ART優(yōu)化
- 用戶隱私所坯,給用戶更多應(yīng)用程序控制權(quán)
- 機(jī)器學(xué)習(xí)
Android 9.0
- 劉海模式谆扎,手機(jī)可以直接設(shè)計(jì)劉海模式
- 夜間模式
- 默認(rèn)使用https
- 非 SDK 接口的限制
- 全面屏
- 后臺(tái)應(yīng)用:
您的應(yīng)用不能訪問(wèn)麥克風(fēng)或攝像頭。
使用連續(xù)報(bào)告模式的傳感器(例如加速度計(jì)和陀螺儀)不會(huì)接收事件芹助。
使用變化或一次性報(bào)告模式的傳感器不會(huì)接收事件燕酷。
如果您的應(yīng)用需要在運(yùn)行 Android 9 的設(shè)備上檢測(cè)傳感器事件,請(qǐng)使用前臺(tái)服務(wù)周瞎。 - 電話信息現(xiàn)在依賴設(shè)備位置設(shè)置 如果用戶在運(yùn)行Android 9 的設(shè)備上停用設(shè)備定位苗缩,則以下函數(shù)不提供結(jié)果:
TelephonyManager.getAllCellInfo()
TelephonyManager.listen()
TelephonyManager.getCellLocation()
TelephonyManager.getNeighboringCellInfo() - Build.SERIAL 始終設(shè)置為 "UNKNOWN" 以保護(hù)用戶的隱私,如果您的應(yīng)用需要訪問(wèn)設(shè)備的硬件序列號(hào),您應(yīng)改為請(qǐng)求 READ_PHONE_STATE權(quán)限声诸,然后調(diào)用getSerial()酱讶。
- 多進(jìn)程 webview 信息訪問(wèn)限制
- 對(duì)使用非 SDK 接口的限制:NoSuchMethodError/NoSuchFieldException
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
// Android P or above
} else {
// below Android P
}
- 檢測(cè)是否使用了非SDK接口 工具veridex
- Apache HTTP 客戶端棄用,需要自定義classloader
- 針對(duì) Android 9 或更高版本并使用前臺(tái)服務(wù)的應(yīng)用必須請(qǐng)求 FOREGROUND_SERVICE 權(quán)限。 這是普通權(quán)限彼乌,因此泻肯,系統(tǒng)會(huì)自動(dòng)為請(qǐng)求權(quán)限的應(yīng)用授予此權(quán)限。
Android 8.0
- 通知中心
- 畫(huà)中畫(huà)(PIP)支持
- 未知來(lái)源應(yīng)用
- 通知渠道
- 應(yīng)用無(wú)法使用其清單注冊(cè)大部分隱式廣播(即慰照,并非專(zhuān)門(mén)針對(duì)此應(yīng)用的廣播)
1.14 請(qǐng)簡(jiǎn)述Apk的安裝過(guò)程灶挟?
復(fù)制APK安裝包到/data/app目錄下,解壓縮并掃描安裝包毒租,向資源管理器注入APK資源稚铣,解析AndroidManifest文件,并在/data/data目錄下創(chuàng)建對(duì)應(yīng)的應(yīng)用數(shù)據(jù)目錄墅垮,然后針對(duì)Dalvik/ART環(huán)境優(yōu)化dex文件惕医,保存到dalvik-cache目錄,將AndroidManifest文件解析出的組件算色、權(quán)限注冊(cè)到PackageManagerService并發(fā)送廣播抬伺。
1.15 Java與JS代碼如何互調(diào)?有做過(guò)相關(guān)優(yōu)化嗎灾梦?WebView峡钓?
java調(diào)js:
可以用loadUrl指定 javascript: 協(xié)議,然后帶上js代碼若河,如
webView.loadUrl("javascript:alert('hello!')")
4.4以后還提供了一個(gè)execJavascript方法能岩,更方便調(diào)用
js調(diào)java:
可以先寫(xiě)好一個(gè)互調(diào)接口類(lèi),用addJavascriptInterface綁定好牡肉,然后js代碼里調(diào)用
注意:api17以后希望被js調(diào)用的需要添加@JavascriptInterface注解捧灰,因?yàn)閍pi17以前存在漏洞淆九,通過(guò)互調(diào)接口的getClass()方法可以拿到Class對(duì)象统锤,之后通過(guò)Class.forName()等一系列反射api可以調(diào)用任何方法
也可以在java層通過(guò)shouldOverrideUrlLoading攔截跳轉(zhuǎn)請(qǐng)求毛俏,js代碼里通過(guò)跳轉(zhuǎn)頁(yè)面?zhèn)鬟f給java
1.16 什么是JNI?具體說(shuō)說(shuō)如何實(shí)現(xiàn)Java與C++的互調(diào)饲窿?
- 在Java類(lèi)中聲明native方法
- 使用javac命令將Java類(lèi)生成class文件
- 使用javah文件生成頭文件
- 編寫(xiě)cpp文件實(shí)現(xiàn)jni方法
- 生成so庫(kù)煌寇,
到此為止,java就可以通過(guò)調(diào)用native方法調(diào)用c++函數(shù)了逾雄,對(duì)于在c++中調(diào)用java方法阀溶,通過(guò)完整類(lèi)名獲取jclass - 根據(jù)方法簽名和名稱獲取構(gòu)造方法id
- 創(chuàng)建對(duì)象(如果要調(diào)用的是靜態(tài)方法則不需要?jiǎng)?chuàng)建對(duì)象)
- 獲取對(duì)象某方法id
- 通過(guò)JNIEnv根據(jù)返回值類(lèi)型、是否是靜態(tài)方法調(diào)用對(duì)應(yīng)函數(shù)即可
1.17 請(qǐng)簡(jiǎn)述從點(diǎn)擊圖標(biāo)開(kāi)始app的啟動(dòng)流程鸦泳?
- 點(diǎn)擊app圖標(biāo)银锻,Launcher進(jìn)程使用Binder IPC向SystemServer進(jìn)程發(fā)起startActivity請(qǐng)求;
- SystemServer進(jìn)程收到1中的請(qǐng)求后做鹰,向zygote進(jìn)程發(fā)送創(chuàng)建新進(jìn)程的請(qǐng)求击纬;
- zygote進(jìn)程fork出新的App進(jìn)程
- App進(jìn)程通過(guò)Binder IPC向SystemServer進(jìn)程發(fā)起attachApplication請(qǐng)求;
- SystemServer進(jìn)程收到4中的請(qǐng)求后钾麸,通過(guò)Binder IPC向App進(jìn)程發(fā)送scheduleLauncherActivity請(qǐng)求更振;
- App進(jìn)程的ApplicationThread線程收到5的請(qǐng)求后,通過(guò)handler向主線程發(fā)送LAUNCHER_ACTIVITY消息饭尝;
- 主線程收到6中發(fā)送來(lái)的Message后肯腕,反射創(chuàng)建目標(biāo)Activity,回調(diào)onCreate等方法钥平,開(kāi)始執(zhí)行生命周期方法实撒,我們就可以看到應(yīng)用頁(yè)面了。