您好,登錄后才能下訂單哦!
在工作中有不少朋友聯(lián)系我,問(wèn)我有沒(méi)有相關(guān)推薦的書(shū)或者資料可以學(xué)習(xí)的。
自己也在不斷的學(xué)習(xí)和提升,所以再這些過(guò)程中吧遇到的面試題整理成了一份983頁(yè)的PDF
(更多完整項(xiàng)目下載。未完待續(xù)。源碼。圖文知識(shí)后續(xù)上傳github。)
可以點(diǎn)擊關(guān)于我聯(lián)系我獲取完整PDF
(VX:×××)
1) Handler線(xiàn)程的消息通訊的橋梁,主要用來(lái)發(fā)送消息及處理消息。
2) Thread普通線(xiàn)程,如果需要有自己的消息隊(duì)列,需要調(diào)用Looper.prepare()
創(chuàng)建Looper
實(shí)例,調(diào)用loop()去循環(huán)消息。
3) HandlerThread
是一個(gè)帶有Looper
的線(xiàn)程,在HandleThread
的run()方法中調(diào)用了Looper.prepare()
創(chuàng)建了Looper
實(shí)例,并調(diào)用Looper.loop()
開(kāi)啟了Loop循環(huán),循環(huán)從消息隊(duì)列中獲取消息并交由Handler處理。利用該線(xiàn)程的Looper
創(chuàng)建Handler實(shí)例,此Handler的handleMessage()
方法是運(yùn)行在子線(xiàn)程中的。即Handler利用哪個(gè)線(xiàn)程的Looper
創(chuàng)建的實(shí)例,它就和相應(yīng)的線(xiàn)程綁定到一起,處理該線(xiàn)程上的消息,它的handleMessage()
方法就是在那個(gè)線(xiàn)程中運(yùn)行的,無(wú)參構(gòu)造默認(rèn)是主線(xiàn)程。
HandlerThread
提供了quit()
/quitSafely()
方法退出HandlerThread
的消息循環(huán),它們分別調(diào)用Looper
的quit和quitSafely
方法,quit會(huì)將消息隊(duì)列中的所有消息移除,而quitSafely
會(huì)將消息隊(duì)列所有延遲消息移除,非延遲消息派發(fā)出去讓Handler去處理。
HandlerThread
適合處理本地IO讀寫(xiě)操作(讀寫(xiě)數(shù)據(jù)庫(kù)或文件),因?yàn)楸镜豂O操作耗時(shí)不長(zhǎng),對(duì)于單線(xiàn)程+異步隊(duì)列不會(huì)產(chǎn)生較大阻塞,而網(wǎng)絡(luò)操作相對(duì)比較耗時(shí),容易阻塞后面的請(qǐng)求,因此HandlerThread
不適合加入網(wǎng)絡(luò)操作。
1) 非靜態(tài)內(nèi)部類(lèi)、匿名內(nèi)部類(lèi):非靜態(tài)內(nèi)部類(lèi)、匿名內(nèi)部類(lèi) 都會(huì)持有外部類(lèi)的一個(gè)引用,如果有一個(gè)靜態(tài)變量引用了非靜態(tài)內(nèi)部類(lèi)或者匿名內(nèi)部類(lèi),導(dǎo)致非靜態(tài)內(nèi)部類(lèi)或者匿名內(nèi)部類(lèi)的生命周期比外部類(lèi)(Activity)長(zhǎng),就會(huì)導(dǎo)致外部類(lèi)在該被回收的時(shí)候,無(wú)法被回收掉,引起內(nèi)存泄露, 除非外部類(lèi)被卸載。
解決辦法:將非靜態(tài)內(nèi)部類(lèi)、匿名內(nèi)部類(lèi) 改成靜態(tài)內(nèi)部類(lèi),或者直接抽離成一個(gè)外部類(lèi)。?如果在靜態(tài)內(nèi)部類(lèi)中,需要引用外部類(lèi)對(duì)象,那么可以將這個(gè)引用封裝在一個(gè)WeakReference
中。
2)靜態(tài)的View:當(dāng)一個(gè)Activity經(jīng)常啟動(dòng),但是對(duì)應(yīng)的View讀取非常耗時(shí),我們可以通過(guò)靜態(tài)View變量來(lái)保持對(duì)該Activity的rootView
引用。這樣就可以不用每次啟動(dòng)Activity都去讀取并渲染View了。但View attach到我們的Window上,就會(huì)持有一個(gè)Context(即Activity)的引用。而我們的View有事一個(gè)靜態(tài)變量,所以導(dǎo)致Activity不被回收。
解決辦法:?在使用靜態(tài)View時(shí),需要確保在資源回收時(shí),將靜態(tài)View detach掉。
3)Handler:在A(yíng)ctivity中定義Handler對(duì)象,那么Handler持有Activty
的引用。而每個(gè)Message對(duì)象是持有Handler的引用的(Message對(duì)象的target屬性持有Handler引用),從而導(dǎo)致Message間接引用到了Activity。如果在Activty destroy
之后,消息隊(duì)列中還有Message對(duì)象,Activty
是不會(huì)被回收的。
解決辦法:?將Handler放入單獨(dú)的類(lèi)或者將Handler放入到靜態(tài)內(nèi)部類(lèi)中(靜態(tài)內(nèi)部類(lèi)不會(huì)持有外部類(lèi)的引用)。如果想要在handler內(nèi)部去調(diào)用所在的外部類(lèi)Activity,可以在handler內(nèi)部使用弱引用的方式指向所在A(yíng)ctivity,在onDestory
時(shí),調(diào)用相應(yīng)的方法移除回調(diào)和刪除消息。
4)監(jiān)聽(tīng)器(各種需要注冊(cè)的Listener,Watcher等):當(dāng)我們需要使用系統(tǒng)服務(wù)時(shí),比如執(zhí)行某些后臺(tái)任務(wù)、為硬件訪(fǎng)問(wèn)提供接口等等系統(tǒng)服務(wù)。我們需要把自己注冊(cè)到服務(wù)的監(jiān)聽(tīng)器中。然而,這會(huì)讓服務(wù)持有 activity 的引用,如果程序員忘記在 activity 銷(xiāo)毀時(shí)取消注冊(cè),那就會(huì)導(dǎo)致 activity 泄漏了。
解決辦法:在onDestory
中移除注冊(cè)
5)資源對(duì)象沒(méi)關(guān)閉造成內(nèi)存泄漏:當(dāng)我們打開(kāi)資源時(shí),一般都會(huì)使用緩存。比如讀寫(xiě)文件資源、打開(kāi)數(shù)據(jù)庫(kù)資源、使用Bitmap資源等等。當(dāng)我們不再使用時(shí),應(yīng)該關(guān)閉它們,使得緩存內(nèi)存區(qū)域及時(shí)回收。
解決辦法:使用try finally結(jié)合,在try塊中打開(kāi)資源,在finally中關(guān)閉資源
6)屬性動(dòng)畫(huà):在使用ValueAnimator
或者ObjectAnimator
時(shí),如果沒(méi)有及時(shí)做cancel取消動(dòng)畫(huà),就可能造成內(nèi)存泄露。因?yàn)樵赾ancel方法里,最后調(diào)用了endAnimation()
; ,在endAnimation
里,有個(gè)AnimationHandler
的單例,會(huì)持有屬性動(dòng)畫(huà)對(duì)象的引用。
解決辦法:在onDestory
中調(diào)用動(dòng)畫(huà)的cancel方法
7)RxJava
:在使用RxJava
時(shí),如果在發(fā)布了一個(gè)訂閱后,由于沒(méi)有及時(shí)取消,導(dǎo)致Activity
/Fragment
無(wú)法銷(xiāo)毀,導(dǎo)致的內(nèi)存泄露。
解決辦法:使用RxLifeCycle
1)內(nèi)存泄漏:指程序中已動(dòng)態(tài)分配的堆內(nèi)存由于某種原因未釋放或無(wú)法釋放,造成系統(tǒng)內(nèi)存的浪費(fèi),導(dǎo)致程序運(yùn)行速度減慢甚至系統(tǒng)奔潰等嚴(yán)重后果。
2)一次內(nèi)存泄漏似乎不會(huì)有大的影響,但內(nèi)存泄漏后堆積的結(jié)果就是內(nèi)存溢出。
3)內(nèi)存泄漏具有隱蔽性,積累性的特征,比其他內(nèi)存非法訪(fǎng)問(wèn)錯(cuò)誤更難檢測(cè)。這是因?yàn)閮?nèi)存泄漏產(chǎn)生的原因是內(nèi)存塊未被釋放,屬于遺漏型缺陷而不是過(guò)錯(cuò)型缺陷。此外,內(nèi)存泄漏不會(huì)直接產(chǎn)生可觀(guān)察的錯(cuò)誤,而是逐漸積累,降低系統(tǒng)的整體性性能。
4)如何有效的進(jìn)行內(nèi)存分配和釋放,防止內(nèi)存泄漏,是軟件開(kāi)發(fā)人員的關(guān)鍵問(wèn)題,比如一個(gè)服務(wù)器應(yīng)用軟件要長(zhǎng)時(shí)間服務(wù)多個(gè)客戶(hù)端,若存在內(nèi)存泄漏,則會(huì)逐漸堆積,導(dǎo)致一系列嚴(yán)重后果。
指程序在申請(qǐng)內(nèi)存時(shí),沒(méi)有足夠的內(nèi)存供申請(qǐng)者使用,或者說(shuō),給了你一塊存儲(chǔ)int類(lèi)型數(shù)據(jù)的存儲(chǔ)空間,但是你卻存儲(chǔ)long類(lèi)型的數(shù)據(jù),就會(huì)導(dǎo)致內(nèi)存不夠用,報(bào)錯(cuò)OOM
,即出現(xiàn)內(nèi)存溢出的錯(cuò)誤。
LruCache
默認(rèn)緩存大小ContentProvider
的權(quán)限管理(解答:讀寫(xiě)分離,權(quán)限控制-精確到表級(jí),URL控制)anr
的時(shí)間限制是多少?ListView
重用的是什么?Parcelable
?Parcelable
的使用?所有的答案,請(qǐng)查看完整的PDF版
(更多完整項(xiàng)目下載。未完待續(xù)。源碼。圖文知識(shí)后續(xù)上傳github。)
可以點(diǎn)擊關(guān)于我聯(lián)系我獲取完整PDF
(VX:×××)
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。