Android中高級面試題【理論知識】

1. ThreadLocal的理解


可以保證線程的安全。在多個線程共享相同的數據的時候,會爲每個線程創建單獨的副本,在單獨的副本上進行數據的操作,不會對其它線程的數據產生影響,保證了線程安全。


2. HashMap HashSet HashTable的區別?


都是集合,底層都是Hash算法實現的。HashMap是Hashtable的替代品,這兩個都是雙列集合,而HashSet是單列集合。HashMap線程不安全、效率高、可以存儲null鍵和null值;Hashtable線程安全,效率低,不可以存儲null鍵和null值。


3. 如何讓HashMap可以線程安全?


HashMap 在併發執行 put 操作時會引起死循環,導致 CPU 利用率接近100%。因爲多線程會導致 HashMap 的 Node 鏈表形成環形數據結構,一旦形成環形數據結構,Node 的 next 節點永遠不爲空,就會在獲取 Node 時產生死循環。
使用下面三種替換方式:
Hashtable
ConcurrentHashMap
Synchronized Map


4. Android對HashMap做了優化後推出的新的容器類是什麼?


SparseArray
它要比 HashMap 節省內存,某些情況下比HashMap性能更好,按照官方問答的解釋,主要是因爲SparseArray不需要對key和value進行auto-boxing(將原始類型封裝爲對象類型,比如把int類型封裝成Integer類型),結構比HashMap簡單(SparseArray內部主要使用兩個一維數組來保存數據,一個用來存key,一個用來存value)不需要額外的額外的數據結構(主要是針對HashMap中的HashMapEntry而言的)。


5. Java多線程之間如何通信


等待喚醒機制


6. 線程池的實現機制


向線程池提交任務,會依次啓動核心線程,如果提交的任務數超過了核心線程數,會將任務保存到阻塞隊列中,如果阻塞隊列也滿了,且繼續提交任務,則會創建新線程執行任務,直到任務數達到最大線程數。此時如果再提交任務的話會拋出異常或者直接丟棄任務。通過Executor.execute()無法得到返回值,通過ExecutorService.submit()可以得到返回值。


7. RxJava中map和flatmap操作符的區別及底層實現


Map返回的是結果集,flatmap返回的是包含結果集的Observable。Map只能一對一,flatmap可以一對多、多對多。
RxJava是通過觀察者模式實現的。


8. 對消息機制中Looper的理解


Looper在消息機制中扮演的角色是創造無限循環從Messagequeue中取得消息然後分發。


先領券再購買雲產品》》


(不限新用戶)雲產品一折拼購直達地址》》aliyunp.com(阿里雲拼團)


(不限新老用戶)阿里雲雙11優惠主會場直達地址》》aliyunh.com(阿里雲優惠)!

9. 單例模式有哪些實現方式


餓漢模式(線程安全,調用效率高,但是不能延時加載)
懶漢模式(線程安全,調用效率不高,但是能延時加載)
雙重檢測鎖模式(由於JVM底層模型原因,偶爾會出問題,不建議使用)
靜態內部類式(線程安全,調用效率高,可以延時加載)
枚舉類(線程安全,調用效率高,不能延時加載,可以天然的防止反射和反序列化調用)


10. 通過靜態內部類實現單例模式有哪些優點


線程安全,調用效率高,可以延時加載


11. synchronized volatile關鍵字有什麼區別?以及還有哪些同樣功能的關鍵字


(1) volatile是變量修飾符,而synchronized則作用於一段代碼或者方法。
(2) volatile只是在線程內存和main memory(主內存)間同步某個變量的值;而synchronized通過鎖定和解鎖某個監視器同步所有變量的值。顯然synchronized要比volatile消耗更多資源。
const、final、lock


12. 界面卡頓的原因有哪些?


UI線程(main)有耗時操作
視圖渲染時間過長,導致卡頓


13. 造成OOM/ANR 的原因?


OOM: (1)不恰當地使用static關鍵字 (2)內部類對Activity的引用 (3)大量Bitmap的使用會導致程序包運行時的內存消耗變大 (4)遊標Cursor對象用完應該及時關閉 (5)加載對象過大 (6)相應資源過多,來不及釋放。
ANR: (1)在5秒內沒有響應輸入的事件(IO操作耗時、數據庫操作複雜耗時、主線程非主線程產生死鎖等待、網絡加載/圖片操作耗時、硬件操作耗時) (2)BroadcastReceiver在10秒內沒有執行完畢(Service binder數量達到上限、Service忙導致超時無響應)


14. Activity與Fragment生命週期有何聯繫


在創建的過程中,是Activity帶領着Fragment,在銷燬的過程中,是Fragment帶領着Activity。
這裏寫圖片描述


15. Glide三級緩存


內存緩存,磁盤緩存、網絡緩存(由於網絡緩存嚴格來說不算是緩存的一種,故也稱爲二級緩存)。緩存的資源分爲兩種:原圖(SOURCE)、處理圖(RESULT)(默認)。
內存緩存:默認開啓的,可以通過調用skipMemoryCache(true)來設置跳過內存緩存,緩存最大空間:每個進程可用的最大內存*0.4。(低配手機0.33)
磁盤緩存:分爲四種:ALL(緩存原圖)、NONE(什麼都不緩存)、SOURCE(只緩存原圖)、RESULT(之後處理圖),通過diskCacheStrategy(DiskCacheStrategy.ALL)來設置,緩存大小250M。


16. MVC、MVP、MVVM的原理


(1) MVC,Model View Controller,是軟件架構中最常見的一種框架,簡單來說就是通過controller的控制去操作model層的數據,並且返回給view層展示。當用戶發出事件的時候,view層會發送指令到controller層,接着controller去通知model層更新數據,model層更新完數據以後直接顯示在view層上,這就是MVC的工作原理。
這裏寫圖片描述
(2) MVP是MVC的演化。MVP的model層相對於MVC是一樣的,而activity和fragment不再是controller層,而是純粹的view層,所有關於用戶事件的轉發全部交由presenter層處理。presenter層充當了橋樑的作用,用於操作view層發出的事件傳遞到presenter層中,presenter層去操作model層,並且將數據返回給view層。
這裏寫圖片描述
(3) MVVM和MVP的區別貌似不大,只不過是presenter層換成了viewmodel層,還有一點就是view層和viewmodel層是相互綁定的關係,這意味着當你更新viewmodel層的數據的時候,view層會相應的變動ui。
這裏寫圖片描述


17. 數據庫的操作類型有哪些,如何導入外部數據庫?


(1) 增刪改查
(2) 將外部數據庫放在項目的res/raw目錄下。因爲安卓系統下數據庫要放在data/data/packagename/databases的目錄下,然後要做的就是將外部數據庫導入到該目錄下,操作方法是通過FileInputStream讀取外部數據庫,再用FileOutputStrean把讀取到的東西寫入到該目錄下。


18. 是否使用過 IntentService,作用是什麼, AIDL 解決了什麼問題?


(1) IntentService繼承自Service。由於Service運行在主線程,無法進行耗時操作。所以你需要在Service中開啓一個子線程,並且在子線程中運行。爲了簡化這一操作,Android中提供了IntentService來進行這一處理。通過查看IntentService的源碼可以看到,在onCreate中,我們開啓了一個HandlerThread線程,之後獲取HandlerThread線程中的Looper,並通過這個Looper創建了一個Handler。然後在onStart方法中通過這個Handler將intent與startId作爲Message的參數進行發送到消息隊列中,然後交由Handler中的handleMessage中進行處理。由於在onStart方法是在主線程內運行的,而Handler是通過工作者線程HandlerThread中的Looper創建的。所以也就是在主線程中發送消息,在工作者接收到消息後便可以進行一些耗時的操作。
(2) 進程間通信


19. 是否使用過本地廣播,和全局廣播有什麼差別?


本地廣播的數據在本應用範圍內傳播,不用擔心隱私數據泄露的問題。不用擔心別的應用僞造廣播,造成安全隱患。相比在系統內發送全局廣播,它更高效。


20. Activity、 Window、 View 三者的差別, fragment 的特點?


(1) Activity像一個工匠(控制單元),Window像窗戶(承載模型),View像窗花(顯示視圖) LayoutInflater像剪刀,Xml配置像窗花圖紙。
(2) a. Fragment可以作爲Activity界面的一部分組成出現;



  1. 可以在一個Activity中同時出現多個Fragment,並且一個Fragment也可以在多個Activity中使用;
  2. 在Activity運行過程中,可以添加、移除或者替換Fragment;
  3. Fragment可以響應自己的輸入事件,並且有自己的生命週期,它們的生命週期會受宿主Activity的生命週期影響。

21. Handler、 Thread 和 HandlerThread 的差別


從Android中Thread(java.lang.Thread -> java.lang.Object)描述可以看出,Android的Thread沒有對Java的Thread做任何封裝,但是Android提供了一個繼承自Thread的類HandlerThread(android.os.HandlerThread -> java.lang.Thread),這個類對Java的Thread做了很多便利Android系統的封裝。
android.os.Handler可以通過Looper對象實例化,並運行於另外的線程中,Android提供了讓Handler運行於其它線程的線程實現,也是就HandlerThread。HandlerThread對象start後可以獲得其Looper對象,並且使用這個Looper對象實例Handler。


22. 低版本 SDK 實現高版本 api


自己實現或使用註解@TargetApi annotation


23. launch mode 應用場景


(1) standard:標準的啓動模式。


這裏寫圖片描述
(2) singleTop:單一頂部模式


如果Activity已經被開啓,並且處於任務棧的棧頂,就不會創建新的Activity,而是複用這個已經開啓的Activity。
爲了防止出現一些奇怪的用戶體驗,推薦使用單一頂部模式,整個任務棧可以有多個實例存在.
應用場景:短信發送界面.
這裏寫圖片描述
(3)singletask:單一任務棧


在整個任務棧裏面只允許有一個當前Activity的實例存在
如果要開啓的Activity在任務棧中已經存在,直接複用這個已經存在的Activity,並且把這個Activity上面的所有的其他Activity給清空
應用場景:如果一個Activity非常消耗內存和cpu資源,建議把這個Activity做成singletask的模式。瀏覽器的browserActivity
這裏寫圖片描述
(4)singleinstance:單一實例.


整個手機操作系統只有一個實例存在,並且是運行在自己單獨的任務棧裏面.
應用場景:通話界面的Activity
這裏寫圖片描述


24. touch 事件傳遞流程


事件處理包括三種情況,分別爲:傳遞—-dispatchTouchEvent()函數、攔截——onInterceptTouchEvent()函數、消費—-onTouchEvent()函數和OnTouchListener。
Android事件傳遞流程:
(1) 事件都是從Activity.dispatchTouchEvent()開始傳遞
(2) 事件由父View傳遞給子View,ViewGroup可以通過onInterceptTouchEvent()方法對事件攔截,停止其向子view傳遞
(3) 如果事件從上往下傳遞過程中一直沒有被停止,且最底層子View沒有消費事件,事件會反向往上傳遞,這時父View(ViewGroup)可以進行消費,如果還是沒有被消費的話,最後會到Activity的onTouchEvent()函數。
(4) 如果View沒有對ACTION_DOWN進行消費,之後的其他事件不會傳遞過來,也就是說ACTION_DOWN必須返回true,之後的事件纔會傳遞進來
(5) OnTouchListener優先於onTouchEvent()對事件進行消費


View不處理事件流程圖
View不處理事件流程圖


View處理事件流程圖
View處理事件流程圖


事件攔截
事件攔截


25.Android性能優化


一、代碼優化


1.使用AndroidLint分析結果進行相應優化
2.不使用枚舉及IOC框架,反射性能低
3.常量加static
4.靜態方法
5.減少不必要的對象、成員變量
6.儘量使用線程池
7.適當使用軟引用和弱引用
8.儘量使用靜態內部類,避免潛在的內存泄露
9.圖片緩存,採用內存緩存LRUCache和硬盤緩存DiskLRUCache
10.Bitmap優化,採用適當分辨率大小並及時回收


二、佈局優化


避免OverDraw過渡繪製
優化佈局層級
避免嵌套過多無用佈局
當我們在畫布局的時候,如果能實現相同的功能,優先考慮相對佈局,然後在考慮別的佈局,不要用絕對佈局。
使用標籤把複雜的界面需要抽取出來
使用標籤,因爲它在優化UI結構時起到很重要的作用。目的是通過刪減多餘或者額外的層級,從而優化整個Android Layout的結構。核心功能就是減少冗餘的層次從而達到優化UI的目的!
ViewStub 是一個隱藏的,不佔用內存空間的視圖對象,它可以在運行時延遲加載佈局資源文件。


三、ListView和GridView優化


1.採用ViewHolder複用convertView
2.避免在getView中執行耗時操作
3.列表在滑動狀態時不加載圖片
4.開啓硬件加速


26.Android內存泄漏


內存泄漏簡單地說就是申請了一塊內存空間,使用完畢後沒有釋放掉。它的一般表現方式是程序運行時間越長,佔用內存越多,最終用盡全部內存,整個系統崩潰。由程序申請的一塊內存,且沒有任何一個指針指向它,那麼這塊內存就泄露了。可能的原因有:
1.註冊沒取消造成內存泄露,如:廣播
2.靜態變量持有Activity的引用
3.單例模式持有Activity的引用
4.查詢數據庫後沒有關閉遊標cursor
5.構造Adapter時,沒有使用 convertView 重用
6.Bitmap對象不在使用時調用recycle()釋放內存
7.對象被生命週期長的對象引用,如activity被靜態集合引用導致activity不能釋放
8.使用Handler造成的內存泄露


先領券再購買雲產品》》


(不限新用戶)雲產品一折拼購直達地址》》aliyunp.com(阿里雲拼團)


(不限新老用戶)阿里雲雙11優惠主會場直達地址》》aliyunh.com(阿里雲優惠)!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章