在工作中有不少朋友聯繫我,問我有沒有相關推薦的書或者資料可以學習的。
自己也在不斷的學習和提升,所以再這些過程中吧遇到的面試題整理成了一份983頁的PDF
(更多完整項目下載。未完待續。源碼。圖文知識後續上傳github。)
可以點擊關於我聯繫我獲取完整PDF
(VX:×××)
Android常見原理性面試專題
1. Handler機制和底層實現
2.Handler、Thread和HandlerThread的差別
1) Handler線程的消息通訊的橋樑,主要用來發送消息及處理消息。
2) Thread普通線程,如果需要有自己的消息隊列,需要調用Looper.prepare()
創建Looper
實例,調用loop()去循環消息。
3) HandlerThread
是一個帶有Looper
的線程,在HandleThread
的run()方法中調用了Looper.prepare()
創建了Looper
實例,並調用Looper.loop()
開啓了Loop循環,循環從消息隊列中獲取消息並交由Handler處理。利用該線程的Looper
創建Handler實例,此Handler的handleMessage()
方法是運行在子線程中的。即Handler利用哪個線程的Looper
創建的實例,它就和相應的線程綁定到一起,處理該線程上的消息,它的handleMessage()
方法就是在那個線程中運行的,無參構造默認是主線程。
HandlerThread
提供了quit()
/quitSafely()
方法退出HandlerThread
的消息循環,它們分別調用Looper
的quit和quitSafely
方法,quit會將消息隊列中的所有消息移除,而quitSafely
會將消息隊列所有延遲消息移除,非延遲消息派發出去讓Handler去處理。
HandlerThread
適合處理本地IO讀寫操作(讀寫數據庫或文件),因爲本地IO操作耗時不長,對於單線程+異步隊列不會產生較大阻塞,而網絡操作相對比較耗時,容易阻塞後面的請求,因此HandlerThread
不適合加入網絡操作。
- 3.handler發消息給子線程,looper怎麼啓動?
- 4.關於Handler,在任何地方new Handler 都是什麼線程下?
- 5.ThreadLocal原理,實現及如何保證Local屬性?
- 6.請解釋下在單線程模型中Message、Handler、Message Queue、Looper之間的關係
- 7.請描述一下View事件傳遞分發機制
- 8.Touch事件傳遞流程
- 9.事件分發中的onTouch 和onTouchEvent 有什麼區別,又該如何使用?
- 10.View和ViewGroup分別有哪些事件分發相關的回調方法
- 11.View刷新機制
- 12.View繪製流程
- 13.自定義控件原理
- 14.自定義View如何提供獲取View屬性的接口?
- 15.Android代碼中實現WAP方式聯網
- 16.AsyncTask機制
- 17.AsyncTask原理及不足
- 18.如何取消AsyncTask?
- 19.爲什麼不能在子線程更新UI?
- 20.ANR產生的原因是什麼?
- 21.ANR定位和修正
- 22.oom是什麼?
(oom(Out Of Memory)內存溢出) - 23.什麼情況導致oom?
- 24.有什麼解決方法可以避免OOM?
- 25.Oom 是否可以try catch?爲什麼?
(可以,當) - 26.內存泄漏是什麼?
內存泄露就是指該被GC垃圾回收的,但被一個生命週期比它長的對象仍然在引用它,導致無法回收,造成內存泄露,過多的內存泄露會導致OOM。
27.什麼情況導致內存泄漏?
1) 非靜態內部類、匿名內部類:非靜態內部類、匿名內部類 都會持有外部類的一個引用,如果有一個靜態變量引用了非靜態內部類或者匿名內部類,導致非靜態內部類或者匿名內部類的生命週期比外部類(Activity)長,就會導致外部類在該被回收的時候,無法被回收掉,引起內存泄露, 除非外部類被卸載。
解決辦法:將非靜態內部類、匿名內部類 改成靜態內部類,或者直接抽離成一個外部類。 如果在靜態內部類中,需要引用外部類對象,那麼可以將這個引用封裝在一個WeakReference
中。
2)靜態的View:當一個Activity經常啓動,但是對應的View讀取非常耗時,我們可以通過靜態View變量來保持對該Activity的rootView
引用。這樣就可以不用每次啓動Activity都去讀取並渲染View了。但View attach到我們的Window上,就會持有一個Context(即Activity)的引用。而我們的View有事一個靜態變量,所以導致Activity不被回收。
解決辦法: 在使用靜態View時,需要確保在資源回收時,將靜態View detach掉。
3)Handler:在Activity中定義Handler對象,那麼Handler持有Activty
的引用。而每個Message對象是持有Handler的引用的(Message對象的target屬性持有Handler引用),從而導致Message間接引用到了Activity。如果在Activty destroy
之後,消息隊列中還有Message對象,Activty
是不會被回收的。
解決辦法: 將Handler放入單獨的類或者將Handler放入到靜態內部類中(靜態內部類不會持有外部類的引用)。如果想要在handler內部去調用所在的外部類Activity,可以在handler內部使用弱引用的方式指向所在Activity,在onDestory
時,調用相應的方法移除回調和刪除消息。
4)監聽器(各種需要註冊的Listener,Watcher等):當我們需要使用系統服務時,比如執行某些後臺任務、爲硬件訪問提供接口等等系統服務。我們需要把自己註冊到服務的監聽器中。然而,這會讓服務持有 activity 的引用,如果程序員忘記在 activity 銷燬時取消註冊,那就會導致 activity 泄漏了。
解決辦法:在onDestory
中移除註冊
5)資源對象沒關閉造成內存泄漏:當我們打開資源時,一般都會使用緩存。比如讀寫文件資源、打開數據庫資源、使用Bitmap資源等等。當我們不再使用時,應該關閉它們,使得緩存內存區域及時回收。
解決辦法:使用try finally結合,在try塊中打開資源,在finally中關閉資源
6)屬性動畫:在使用ValueAnimator
或者ObjectAnimator
時,如果沒有及時做cancel取消動畫,就可能造成內存泄露。因爲在cancel方法裏,最後調用了endAnimation()
; ,在endAnimation
裏,有個AnimationHandler
的單例,會持有屬性動畫對象的引用。
解決辦法:在onDestory
中調用動畫的cancel方法
7)RxJava
:在使用RxJava
時,如果在發佈了一個訂閱後,由於沒有及時取消,導致Activity
/Fragment
無法銷燬,導致的內存泄露。
解決辦法:使用RxLifeCycle
28.內存泄漏和內存溢出區別?
(1)內存泄漏
1)內存泄漏:指程序中已動態分配的堆內存由於某種原因未釋放或無法釋放,造成系統內存的浪費,導致程序運行速度減慢甚至系統奔潰等嚴重後果。
2)一次內存泄漏似乎不會有大的影響,但內存泄漏後堆積的結果就是內存溢出。
3)內存泄漏具有隱蔽性,積累性的特徵,比其他內存非法訪問錯誤更難檢測。這是因爲內存泄漏產生的原因是內存塊未被釋放,屬於遺漏型缺陷而不是過錯型缺陷。此外,內存泄漏不會直接產生可觀察的錯誤,而是逐漸積累,降低系統的整體性性能。
4)如何有效的進行內存分配和釋放,防止內存泄漏,是軟件開發人員的關鍵問題,比如一個服務器應用軟件要長時間服務多個客戶端,若存在內存泄漏,則會逐漸堆積,導致一系列嚴重後果。
(2)內存溢出
指程序在申請內存時,沒有足夠的內存供申請者使用,或者說,給了你一塊存儲int類型數據的存儲空間,但是你卻存儲long類型的數據,就會導致內存不夠用,報錯OOM
,即出現內存溢出的錯誤。
- 29.
LruCache
默認緩存大小
(4MB) - 30.
ContentProvider
的權限管理(解答:讀寫分離,權限控制-精確到表級,URL控制) - 31.如何通過廣播攔截和abort一條短信?
- 32.廣播是否可以請求網絡?
- 33.廣播引起
anr
的時間限制是多少? - 34.計算一個view的嵌套層級
- 35.Activity棧
- 36.Android線程有沒有上限?
- 37.線程池有沒有上限?
- 38.
ListView
重用的是什麼? - 39.Android爲什麼引入
Parcelable
? - 40.有沒有嘗試簡化
Parcelable
的使用?
所有的答案,請查看完整的PDF版
(更多完整項目下載。未完待續。源碼。圖文知識後續上傳github。)
可以點擊關於我聯繫我獲取完整PDF
(VX:×××)