2020 Android面試

1.接口的意義
1.提供一種協議()
2.提高代碼可維護性和擴展性
3.在團隊合作中,代碼規範性
2.抽象類的意義
1.爲子類提供一個公共的類型
2.封裝子類內重複內容(成員變量和方法)
3.定義有抽象方法,子類雖然有不同的實現,但該方法的定義是一致的。
3.哪些情況下的對象會被垃圾回收機制處理掉
1.引用計數法
2. 可達性分析算法
4.進程和線程的區別
根本區別:進程是操作系統資源分配的基本單位,而線程是任務調度和執行的基本單位

在開銷方面:每個進程都有獨立的代碼和數據空間(程序上下文),程序之間的切換會有較大的開銷;線程可以看做輕量級的進程,同一類線程共享代碼和數據空間,每個線程都有自己獨立的運行棧和程序計數器(PC),線程之間切換的開銷小。

所處環境:在操作系統中能同時運行多個進程(程序);而在同一個進程(程序)中有多個線程同時執行(通過CPU調度,在每個時間片中只有一個線程執行)

內存分配方面:系統在運行的時候會爲每個進程分配不同的內存空間;而對線程而言,除了CPU外,系統不會爲線程分配內存(線程所使用的資源來自其所屬進程的資源),線程組之間只能共享資源。

包含關係:沒有線程的進程可以看做是單線程的,如果一個進程內有多個線程,則執行過程不是一條線的,而是多條線(線程)共同完成的;線程是進程的一部分,所以線程也被稱爲輕權進程或者輕量級進程。
5.java中==和equals和hashCode的區別

基本數據類型比較的是值,引用類型(接口、類、數組)運用比較的是內存中的存放地址
6.什麼導致線程阻塞
1.線程睡眠Thread.sleep
2.線程等待Thread.wait(),等待notify喚醒
3.線程禮讓Thread.yield()
4.線程自閉Thread.join()
5.suspend() 和 resume() 方法
7.死鎖的四個必要條件
1.互斥
2.請求和保持
3.循環等待
4.不可剝奪
8.進程優先級
前臺線程-》可見進程-》服務進程-》後臺進程-》空進程
9.ArrayMap對比HashMap
HashMap內部採用數組+鏈表的形式存儲數據,默認容量爲16,加載因子爲0.75,達到16*0.75擴容到2倍
ArrayMap適合item小於1000的場景尤其是插入數據和刪除數據不頻繁的情況。並且Map中放置10.容器類之間的區別
List有序
Set唯一
Map用於存儲key,value
11.抽象類接口區別

12.如何導入外部數據庫
數據庫本質就是文件

android系統下數據庫應該存放在 /data/data/com…(package name)/ 目錄下

所以導入數據庫其實就是文件的複製操作

用到的就是文件流FileInputStream,熟悉java的話可以輕鬆的完成文件的複製
13.本地廣播和全局廣播有什麼差別
LocalBroadcastReceiver不能靜態註冊,只能採用動態註冊的方式。
在發送和註冊的時候採用,LocalBroadcastManager的sendBroadcast方法和registerReceiver方法
14.intentService作用是什麼,AIDL解決了什麼問題
15.如何保證Service在後臺不被kill
1、Service設置成START_STICKY(onStartCommand方法中),kill 後會被重啓(等待5秒左右),重傳Intent,保持與重啓前一樣

2、通過 startForeground將進程設置爲前臺進程,做前臺服務,優先級和前臺應用一個級別​,除非在系統內存非常缺,否則此進程不會被 kill.具體實現方式爲在service中創建一個notification,再調用void android.app.Service.startForeground(int id,Notificationnotification)方法運行在前臺即可。

3、雙進程Service:讓2個進程互相保護,其中一個Service被清理後,另外沒被清理的進程可以立即重啓進程

4、AlarmManager不斷啓動service。該方式原理是通過定時警報來不斷啓動service,這樣就算service被殺死,也能再啓動。同時也可以監聽網絡切換、開鎖屏等廣播來啓動service。
參考實現方式如下:

Intent intent =new Intent(mContext, MyService.class);

PendingIntent sender=PendingIntent

.getService(mContext, 0, intent, 0);

AlarmManager alarm=(AlarmManager)getSystemService(ALARM_SERVICE);

alarm.setRepeating(AlarmManager.RTC_WAKEUP,System.currentTimeMillis,5*1000,sender);

該方式基本可以保證在正常運行情況下,以及任務欄移除歷史任務後(小米、魅族手機除外),service不被殺死。但是360等軟件管家依然可以殺死。另外還有不斷啓動的邏輯處理麻煩。

5、QQ黑科技:在應用退到後臺後,另起一個只有 1 像素的頁面停留在桌面上,讓自己保持前臺狀態,保護自己不被後臺清理工具殺死

6、在已經root的設備下,修改相應的權限文件,將App僞裝成系統級的應用(Android4.0系列的一個漏洞,已經確認可行)

Android系統中當前進程(Process)fork出來的子進程,被系統認爲是兩個不同的進程。當父進程被殺死的時候,子進程仍然可以存活,並不受影響。鑑於目前提到的在Android-Service層做雙守護都會失敗,我們可以fork出c進程,多進程守護。死循環在那檢查是否還存在,具體的思路如下(Android5.0以下可行)
用C編寫守護進程(即子進程),守護進程做的事情就是循環檢查目標進程是否存在,不存在則啓動它。
在NDK環境中將1中編寫的C代碼編譯打包成可執行文件(BUILD_EXECUTABLE)。
主進程啓動時將守護進程放入私有目錄下,賦予可執行權限,啓動它即可。
7、聯繫廠商,加入白名單

16:如何優化自定義View
(1)減少不必要的代碼:對於頻繁調用的方法,需要儘量減少不必要的代碼。

(2)不在 onDraw 中做內存分配的事:先從 onDraw 開始,需要特別注意不應該在這裏做內存分配的事情,因爲它會導致 GC,從而導致卡頓。在初始化或者動畫間隙期間做分配內存的動作。不要在動畫正在執行的時候做內存分配的事情。

(3)減少 onDraw 被調用的次數:大多數時候導致 onDraw 都是因爲調用了 invalidate().因此請儘量減少調用 invaildate()的次數。如果可能的話,儘量調用含有 4 個參數的 invalidate()方法而不是沒有參數的 invalidate()。沒有參數的 invalidate 會強制重繪整個 view。

(4)減少 layout 的次數:一個非常耗時的操作是請求 layout。任何時候執行 requestLayout(),會使得 Android UI 系統去遍歷整個View 的層級來計算出每一個 view 的大小。如果找到有衝突的值,它會需要重新計算好幾次。

(5)選用扁平化的 View:另外需要儘量保持 View 的層級是扁平化的(去除冗餘、厚重和繁雜的裝飾效果),這樣對提高效率很有幫助。

(6)複雜的 UI 使用 ViewGroup:如果你有一個複雜的 UI,你應該考慮寫一個自定義的 ViewGroup 來執行他的 layout 操作。(與內置的view 不同,自定義的 view 可以使得程序僅僅測量這一部分,這避免了遍歷整個 view 的層級結構來計算大小。)繼承 ViewGroup作爲自定義 view 的一部分,有子 views,但是它從來不測量它們。而是根據他自身的 layout 法則,直接設置它們的大小。

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