Android開發工程師面試題彙總(持續更新...)

1.activity的四種啓動模式和應用場景

1.standard標準模式:每次創建一個activity都會重新創建一個新的實例,不管這個實例是否已經存在。
2.singleTop棧頂複用模式:如果activity已經位於任務棧的棧頂,那麼此activity不會被重新創建,同時會調用onNewIntent方法,如果activity實例已經存在但不位於棧頂,那麼activity仍然會被重新創建。
3.singleTask棧內複用模式:只要activity在一個任務棧中存在,那麼多次啓動此activity都不會重新創建實例,並回調onNewIntent方法,此模式啓動activity,系統首先會尋找是否存在A想要的任務棧,如果不存在,就會重新創建一個任務棧,然後把創建號A的實例放到任務棧中,這種模式具有clearTask的功能,他會把在此activity之上的任務棧出棧。
4.singleInstance單實例模式:這是一種加強的singleTask模式,具有此種模式的activity只能單獨地位於一個任務棧中,且此任務棧中只有唯一一個實例。

2.FragmentPagerAdapter 與FragmentStatePagerAdapter的區別與使用場景

答案:FragmentPagerAdapter 的每個fragment會持久的保存在ftagmentManager中,只要用戶可以返回到頁面中,它都不會被銷燬。因此適用於那些數據相對靜態的頁面,fragment數量也比較少的那種;fragmentStatePagerAdapter只保留當前頁面,當頁面不可見時,該fragment就會被消除,釋放其資源。因此適用於那些數據動態性較大,佔用內存較多,多fragment的情況。

3.如何對圖片進行緩存

答案:先從內存中讀取,如果沒有從磁盤中讀取,如果沒有從網絡獲取顯示,我們應該考慮哪些應該緩存,獲取成本,緩存成本,緩存的價值。哪些應該丟棄?什麼時候丟棄?這個時候我們就需要考慮到算法了。
1.LRU算法:(最近最少使用算法)算法的核心思想就是最近最少使用。它在算法的內部維護了一個LinkHashMap的鏈表,通過put數據的時候判斷內存是否已經滿了,如果滿了,則將最近最少使用的數據給剔除掉,從而達到內存不會爆滿的狀態。因爲LinkHashMap內部是一個數組雙向鏈表的形式來存儲數,他能夠保證插入時候的數據和取出來的時候數據的順序性一致,也就是說我們以什麼樣的順序插入數據,就會以什麼樣的順序取出數據。並且最重要的一點是,當我們通過get方法獲取數據的時候,這個獲取的數據會從隊列中跑到隊列頭來,從而很好的滿足我們LRUCache算法的設計思想。
2.LFU算法(最近不經常使用原則):使用次數最少的,當內存不足時會首先被幹掉。
舉例說明:我們熟悉的GLide圖片加載框架就是使用LRuCache算法,內部也是基於LinedHashMap來實現的。

4.橫豎屏切換,生命週期的變化

1.當不設置activity的android:configCahnges時,切屏會重新調用各個生命週期,切橫屏時會執行一次,切豎屏時會執行兩次。
2.當設置activity的android:configChanges="orientation"時,切屏還是會重新調用各個生命週期,切橫,豎屏時只會執行一次。
3…當設置activity的an。droid:configChanges="orientation|keyboardHidden"時,切屏不會重新調用各個生命週期,只會執行onConfigurationChanged方法。

5.加密算法有哪些?對稱加密和非對稱加密的區別?

一.非對稱密鑰加密的使用過程:
A要向B發送信息,A和B都要產生一對用於加密和解密的公鑰和私鑰。A要給B發送信息時,A用B的公鑰加密信息,B收到這個消息後,B用自己的私鑰解密A的消息,其他所有收到這個報文的人都無法解密,因爲只有B纔有B的私鑰。 反過來,B向A發送消息也是一樣。
二.對稱加密和非對稱加密的區別 :
1.對稱加密加密與解密使用的是同樣的密鑰,所以速度快,但由於需要將密鑰在網絡傳輸,所以安全性不高。
2.非對稱加密使用了一對密鑰,公鑰與私鑰,所以安全性高,但加密與解密速度慢。
3.解決的辦法是將對稱加密的密鑰使用非對稱加密的公鑰進行加密,然後發送出去,接收方使用私鑰進行解密得到 對稱加密的密鑰,然後雙方可以使用對稱加密來進行溝通。

6.IntentService

答案:當Service中執行耗時操作時,20s會產生ANR,而IntentService是一個特殊的Service,則可用於執行後臺耗時的任務,無需處理多線程問題,IntentService封裝了HandlerThread和Handler,通過複寫onHandleIntent方法操作耗時操作, 當任務執行完後會自動停止,無需調用stopSelf()方法停止Service,避免了Service的內存泄漏,Intentservice若未執行完成上一次的任務,將不會新開一個線程,是等待之前的任務完成後,再執行新的任務,等任務完成後再次調用stopSelf,適合執行一些高優先級的後臺任務,因爲不容易被殺死。

7.Android怎麼加速啓動Activity(優化的細節)

答案:減少onCreate的時間,耗時操作,移除背景,在很多的應用一開始點擊的時候總會出現黑屏或者白屏,甚至前段時間微信也有同樣的問 題。其實白屏或者黑屏還是一些其他的東西,都是因爲 Android 主題的問題,只要自己自 定義一個啓動主題,問題完美解決。

8.ANR

答案:Application Not Responding,"應用無響應"對話框。
1.產生原因:Activity 5s、Service 10s、Broadcast 20s
2.如何解決:分析log,/data/anr/traces.txt,主要看main Thread CPU usage和是否block死鎖
3.如何避免ARN?
3.1.UI線程儘量只做跟UI相關的工作
3.2.耗時的工作(比如數據庫操作,I/O,連接網絡或者別的有可能阻礙UI線程的操作)把它放入單獨的線程處理
3.3.儘量用Handler來處理UIthread和別的thread之間的交互。

9.使用SparseArray替代HashMap?

答案:SparseArray不需要開闢內存空間來額外存儲外部映射,從而節省內存。僅僅提高內存效率,而不是提高執行效率,所以也決定它只適用於android系統(內存對android項目有多重要,地球人都知道)。SparseArray執行效率比 HashMap要慢一點,因爲查找需要折半查找,而添加刪除則需要在數組中執行,而HashMap都是通過外部映射。

10.map的4種遍歷方式及性能比較?

一.效率比較
1.entrySet的方式整體都是比keySet方式要高一些;
2.單純的獲取key來說,兩者的差別並不大,但是如果要獲取value,還是entrySet的效率會更好,因爲keySet需要從map中再次根據key獲取value,而entrySet一次都全部獲取出來;
3.iterator的迭代器方式比foreach的效率高。
二、foreach和iterator
其實foreach的語法只是對iterator進行了簡單的包裝,使用起來更加方便而已,但是如果在foreach循環體內,對集合元素進行刪除添加操作的時候,會報出ConcurrentModificationException,併發修改異常。如果需要在遍歷集合的時候對象集合中元素進行刪除操作,需要使用iterator的遍歷方式,iterator自帶的remove刪除方式不會報出異常。

11.Android自定義view流程

1.自定義屬性的聲明與獲取:
分析需要的自定義屬性,在res/values/attrs.xml定義聲明, 在layout.xml文件中使用,在view的構造方法中進行獲取。
2.測量onMeasure:
設置測量模式,從MeasureSpec中獲取 EXACTLY→match_parent,AT_MOST→wrap_content,UNSPECIFIED不受限制,三種模式。調用ViewGroup中的onMeasure方法。在方法中調用了measureChild方法,執行了所有子控件的onMesure方法測繪出所有的子控件的大小。調用setMeasureDimension方法 設置測繪後的大小。
3.佈局onLayout(ViewGroup):
決定子view的位置,儘可能將onMeasure中操作移動到此方法中,比如耗時,初始化等操作,因爲此方法只執行一次,調用requestLayout(),會調用measure()過程 和 layout()過程
4.繪製onDraw:
使用canvas和paint畫筆進行繪製,invalidate()可在U線程調用, postInvalidate()在子線程中調用,重繪,假如視圖發生大小沒有變化就不會調用layout()過程,只調用onDraw過程。

12.安卓view的事件分發機制

事件的分發過程是自上而下,由外向內的,事件總是先傳遞給父元素,由父元素分發給子view。
1.當一個viewGroup需要處理事件時如果onInterceptTouchEvent方法返回true,表示要攔截當前事件,則viewGroup的onTouchEvent方法會被調用,如果返回false,就會傳遞給它的子元素,子元素的onInterceptTouchEvent方法會被調用 。
2.當一個view需要處理事件時,如果它設置了onTouchListener,那麼onTouchListener的onTouch方法會被調用,如果返回onTouch返回false,則當前view的onTouchEvent方法會被調用,如果返回true,將不會調用。

13.jni調用過程

比如我們要在項目中把密鑰等一些私密信息存儲到.so文件中,那我們如何生成.so文件並調用呢?主要分爲以下幾個步驟:
1.新建AppSecrectUtils.class,編寫調用c文件的方法,使用 System.loadLibrary加載.so文件,定義native方法。
2.make project 生成對應的.class文件。
3.根據.class文件生成.h文件,找到項目路徑,進入命令輸入頁面, javah -d jni -classpath 編譯後的class文件的絕對路徑。
4.根據AppSecretUtils類編寫main.c文件。實現native的方法
5.添加Android.mk文件,可以定義.so文件的名稱等。
6.添加aplication.mk文件,可以設置生成哪些類型的.so文件。
7.找到項目路徑進入到命令提示符界面,然後輸入 ndk-build命令,即可在項目的libs文件中生成.so文件。
8.在你的項目中新建一個路徑,必須與生成.so文件時中的AppSecretUtils包名路徑一致,然後新建一個類AppSecretUtils名字也是保持一致。使用 System.loadLibrary加載.so文件,定義生成.so文件時的native方法,然後就可以在項目中使用AppSecretUtils進行調用相應的方法了。

14.http請求報文

1.請求行、由方法字段、URL 字段 和HTTP 協議版本字段 3 個部分組成,他們之間使用空格隔開
2.請求頭部、請求頭部由關鍵字/值對組成,典型的請求頭有:User-Agent:產生請求的瀏覽器類型;Accept-Encoding:客戶端可接受的編碼壓縮格式; Host:請求的主機名.
3/空行 最後一個請求頭之後是一個空行,發送回車符和換行符,通知服務器以下不再有請求頭;
4.請求包體 包體類型 Content-Type 和包體長度 Content-Length;

15.http響應報文

1.狀態行、HTTP 協議版本字段、狀態碼和狀態碼的描述文本 3 個部分組成
2.響應頭部、包含了服務器用來處理請求的軟件信息及其版本 Connection:連接方式;
3.空行
4.響應包體 服務器返回給客戶端的文本信息;

16.handler總結

1.作用:handler用來處理主線程與子線程之間通信的工具
2.原理:handler封裝了消息的發送,內部跟Looper進行關聯,Handler負責發送消息,Looper負責接收Handler發送的消息,並直接把消息回傳給Handler自己,MessageQueue就是一個存儲消息的容器。
3.爲什麼要設計只能通過Handler機制更新UI呢? 最根本的目的就是解決多線程併發問題.
4.主線程中Looper的輪詢死循環爲何沒有阻塞主線程?
ActivityThread的main方法主要就是做消息循環,一旦退出消息循環,那麼你的應用也就退出了。 因爲Android 的是由事件驅動的,looper.loop() 不斷地接收事件處理事件,每一個點擊觸摸或者說Activity的生命週期都是運行在 Looper.loop() 的控制之下,如果它停止了,應用也就停止了。只能是某一個消息或者說對消息的處理阻塞了 Looper.loop(),而不是 Looper.loop() 阻塞它。

17.HTTP和HTTPS的區別

1.HTTP協議使用默認80端口,HTTPS協議使用443端口
2.HTTPS協議需要到CA申請證書,一般免費的證書較少,需要交費
3.HTTP信息是明文傳輸,HTTPS使用具有安全性的SSL加密傳輸信息
4、http的連接很簡單,是無狀態的。Https協議是由SSL+Http協議構建的可進行加密傳輸、身份認證的網絡協議,比http協議安全。 (無狀態的意思是其數據包的發送、傳輸和接收都是相互獨立的。無連接的意思是指通信雙方都不長久的維持對方的任何信息。)

18.android中Invalidate和postInvalidate的區別

答案:invalidate是在ui線程中使用,postInvalidate在非ui線程種使用,使用invalidate更新view時需要配合handler來使用,但是postInvalidate是不需要的,在線程種可以直接使用,通過postInvalidate的源碼可知,它也是使用到了handler來進行處理的。

19.wait和sleep 的區別

答案:wait是Object的方法,wait是對象鎖,鎖定方法不讓繼續執行,當執行notify方法後就會繼續執行,sellp是Thread的方法, sellp是使線程睡眠,讓出cpu,結束後自動繼續執行。

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