我們在平時或面試遇到這些問題時,我們應該怎麼回答?
1. 整體性能如何探測,有哪方面 什麼指標,怎麼保證更流暢
2. 講講架構這塊,如何解耦,大項目邏輯多怎麼辦。3. android的發展大事件和主要技術發展4. avtivity(service)啟動流程簡述5. 動態化的幾種方案6. 熱修復的原理
7. 網路這塊怎麼優化8. 資料庫性能怎麼保證9. 線程安全怎麼保證,非同步並發這塊你怎麼做的
這幾個問題是我根據自己的面試經歷總結的,朋友 @AndWang 幫分享出來,大家一起交流學習。
其實不一定面試時才了解這些,並且了解絕對不是重點,而是實踐,絕知此事要躬行是真理,這樣的問題也似乎沒有「最佳答案」,但是可以發表一下自己觀點和實踐結論。
有些做法或觀點一下子想不起來,需要具體做的時候再google一下,或者跟朋友溝通拓展一下,所以先做個簡單的回答,請大家補充。
1. App性能如何探測,有哪些方面,什麼指標,怎麼保證更流暢?
性能可以根據幀率、內存、CPU、GPU等指標的數據和表現輔助判斷,可以從/proc文件夾下讀取文件獲取cpu、內存等信息,也可以用dumpsys命令獲取幀率等信息,也可以通過android API獲取相關信息。
還有很多性能相關的分析工具很重要,輔助判斷和分析,比如Heap Tool、Memory Monitor、Lint、HierarchyView、WireShark、TraceView等。
保證流暢有很多點可以去研究,比如布局、代碼、緩存、網路、資料庫、非同步並發等方面的優化,涉及很多的知識點,可以google下,先簡單說下,有時間再細述。
- 布局充分利用include、viewstub、merge 等標籤,控制層級,避免過度渲染(繪製)。
- 代碼上盡量使用final、局部變數、系統函數如arraycopy等、位移操作是否可以代替乘除、for循環是否可以避免size計算和new對象等等。
- 緩存方面,線程、點陣圖、視圖、網路數據是否可以被緩存,IO用緩衝流。
- 網路方面,如盡量避免輪詢,控制節奏和頻率,IP直連,採用SPDY方案(或HTTP2.0)來實現壓縮header、多路復用、雙向通信等,API數據壓縮,多個請求是否可以合併,數據壓縮和嘗試protocol buffer相關序列化方案。
- 資料庫方面,嘗試用SQLiteStatement代替SQLiteDatabase完成操作,索引和事務的充分理解和使用,注意SQL語句語法和拼接,採用部分查詢和延遲載入。
- 非同步並發方面,全App只有一個線程池,控制核心並發數量,控制超載時排隊數量和策略,合理調度任務,優化業務邏輯。
- 最後關於幀率,你看到的視覺卡頓,直接原因基本是「掉幀」。關於幀率,盡量保證主線程里做的事情,不會超過16毫秒(其實這挺難的),16毫秒大法好,具體可以去理解下CPU、GPU、屏幕三者如何配合完成渲染的,推薦老羅的博客。
2. 談談架構。大項目,邏輯多怎麼辦,如何應對多App和多終端?
適當參考我在知乎的一個回答 怎樣搭高質量的Android項目框架,框架的結構具體描述? - 馬天宇的回答 ,結合模塊化、組件化思想去做,多實踐一下mvp、mvvm等策略。
3. android的發展大事件和主要技術發展
額,挺多的,朋友們補充吧。
這個問題蠻好的 Android 開發有哪些新技術出現? - Android 應用4. avtivity(service)啟動流程簡述
可以自己閱讀源代碼,結合羅老師的博客,研究的非常棒:Android應用程序啟動過程源代碼分析
5. 動態化的幾種方案
早期的H5方案,通過js和java互通增強h5的能力。
還有DexClasssLoader結合反射代理的方案。還有React Native方案,手淘的Weex框架。還有Lua等腳本實現動態化方案。6. 熱修復的原理
Github上讀一下AndFix這個項目的源碼,還有xposed、dexposed。
大致原理就是將java方法通過c/c++修改屬性變為public native方法,上下文攜帶到native層,然後根據上下文指向另一個java方法,從而「偷梁換柱」,如果是支持ART的手機,那麼策略不一樣,將bug method的關鍵信息(classloader、theadid等)保留,將修復過的方法的各種信息賦給bug method,完成「移花接木」。
另外,其實有挺多的策略改變運行時行為的,比如:- Javasisst:位元組碼修改類庫,依賴位元組碼修改和DX類庫,可以完成動態替換和切面編程。
- AspectJ:依賴位元組碼編織器,需要按照其語法來編寫,需要一點「編織」時間。
- Xposed方案,簡直是一個Bug,神器般的存在,沒準以後會被Android系統修復呢,不僅可以改變自己的類行為還可以hook系統的方法,root過的機器還可以hook其他App和系統進程。
7. 網路這塊怎麼優化
盡量避免輪詢,控制節奏和頻率。
IP直連節省DNS解析時間。
嘗試其他數據序列化方案比如protocol buffer等。
採用SPDY方案(或HTTP2.0)來壓縮header、多路復用、雙向通信等。
伺服器做優化,比如分散式、緩存之類的,減少API涉及的業務操作所需要的時間嘛。
API介面數據精簡,多個請求是否可以合併,增量請求啊、GIP壓縮啊什麼的,等等。
8. 資料庫性能怎麼保證
嘗試使用SQLiteStatement取代SQLiteDatabase對象完成操作,避免直接使用SQLiteDatabase提供的update、inset等方法。
索引和事務的充分理解和使用,批量操作使用事務極大提升速度,這個我是做過試驗的,效果驚人。
SQL語句拼接和本身的優化,僅查詢部分局部數據,使用延遲載入策略。
10萬條數據插入比系統SQLiteDatabase操作快一倍,推薦我的LiteOrm資料庫框架 GitHub - litesuits/android-lite-orm: LiteOrm is a fast, small, powerful ORM framework for Android. LiteOrm makes you do CRUD operarions on SQLite database with a sigle line of code efficiently.。
9. 線程安全怎麼保證,非同步並發這塊你怎麼做的
理解並使用ReentrantLock,Synchronized保護對象或過程,final來保護不可變對象,無狀態和只讀對象是安全的,合理使用一些 concurrent容器,比如ConcurrentHashmap等,重量級耗時任務考慮是否可以釋放鎖,多線程下實例化或延遲載入需要保護起來,保護多線程下關鍵數據訪問的原子性,等等還有很多的。。。
推薦研究下Doug Lea主寫和設計的java concurrent包,理解CountDownLatch、CyclicBarrier、Semaphore、FutureTask等對象。
具體開上,我使用自己寫的SmartExecutor,直接繼承ExecutorService,封裝了一個公共線程池,全App保證只有一個線程池。源碼在這個開源項目里:GitHub - litesuits/android-lite-http: LiteHttp is a simple, intelligent and flexible HTTP framework for Android. With LiteHttp you can make HTTP request with only one line of code! It could convert a java model to the parameter and rander the response JSON as a java model intelligently. 。
在一個 App 中 SmartExecutor 可以有多個實例,每個實例都有獨立核心和等待線程數指標,每個實例都有獨立的調度和滿載處理策略,但它們 共享一個線程池。這種機制既滿足不同木塊對線程式控制制和任務調度的獨立需求,又共享一個池資源。獨立又共享,最大程度上節省資源,提升性能。
控制核心並發數,盡量和CPU核數保持一致(或者多兩個)我認為吞吐量是最佳的,線程過多則調度線程消耗CPU和時間,過少則不能充分利用多核的能力。
控制排隊策略和排隊數量,是否考慮新任務先處理,過度超載丟掉最老的任務。
還有就是業務上,合理調度任務,優化業務邏輯,不要胡搞亂搞,不作惡。
最後我想推薦一下我的個人開源項目:http://litesuits.com?f=zh_perf,歡迎關注嘛。在朋友圈看到 @馬天宇馬老師的分享,本來以為只能膜拜,逛知乎的時候通過Timeline發現了這個問題,實在是太開心了,因為可以和大嬸回答同一個問題了。
馬老師的回答已經很詳細了,如果再一一回答肯定回答得沒有他好,也獲得不到很多贊,索性機智一點分享與題目相關的幾個鏈接,希望對題主有幫助。- 值得推薦的Android應用性能檢測工具列表(回答問題1)
- 胡凱(回答問題1、7、8)
- 移動端的網路優化,不限於 Android,同樣適用於 iOS 和 H5(回答問題7)
- Issues · android-cn/android-discuss · GitHub(回答所有問題)
- 利用 DexClassLoader 實現 Android 插件化,從而達到動態載入(回答問題5)
- 本文為性能優化系列的總綱,主要介紹性能調優專題計劃、何為性能問題、性能調優方式及前面介紹的資料庫優化、布局優化、Java(Android)代碼優化具體對應的調優方式。(回答問題7、8)
- 線程池 | Trinea(回答問題9)
- Android 開發有哪些新技術出現? - Android 應用(回答問題3)
- GitHub - alibaba/AndFix: AndFix is a library that offer hot-fix for Android App.(回答問題6)
性能優化的最好方法,就是買通產品經理
試著回答一下有關網路優化的吧,今天正好複習了一些:
1.使用post的時候對body使用gzip壓縮,http 2.0也支持對header壓縮,順便可以講一下http 2.0有哪些優化(多路復用、雙向通信等);
2.對數據進行Prefetch(預取)。比如在一個預覽頁面里可以先請求將要訪問的詳情頁的數據,打開詳情頁的時候就直接顯示了,注意需要根據網路狀況(2G、3G/4G、wifi等,也可進一步獲取實際的網速)確定合理的Prefetch數據量,數據多了反而影響了速度、少了達不到效果;
3.斷點下載可以使用多線程方式,第一次請求完可以從response header里獲取etag和last-modified欄位,下次請求的時候帶上,如果沒有改變etag並且時間沒到則返回304,直接使用緩存;4.減小返回數據量。一方面客戶端獲取API數據時可以使用gzip壓縮;另一方面服務端可以根據設備尺寸、網路情況等返回不同解析度圖片,使用JSON、protobuf代替XML,WebP代替其他圖片格式;5.設置合理的同步頻率。對於一些需要經常同步數據的需求,不要過於頻繁的請求數據。比如上一次請求後沒有新數據的話,下一次請求間隔可以加倍,避免頻繁的請求耗盡手機電量;另外在網路狀況不好時可以採用Batch策略,即將請求放入一個隊列里,等待網路狀況好轉時才一起去請求;其他諸如IP直連、請求合併、連接復用(keep-alive)等也有人提到了,就不再說了。
再更新一下有關界面UI優化的:
1.減少布局深度。如多使用RelativeLayout替代LinearLayout、merge/include的靈活使用;2.自定義View重寫onDraw( )時,在該方法內不要執行耗時操作、也盡量不要創建對象;3.減少Overdraw。被遮蓋的背景、view等可以考慮移除,自定義View在onDraw( )里可通過canvas.clipRect( )指定繪製區域跳過不需繪製的區域;4.比較偏門的一個點:少用weight屬性。因為使用了它,布局會進行多一次Measure操作,具體可以看view繪製的源碼;希望大家都面試順利~
講講架構這塊,如何解耦,大項目邏輯多怎麼辦。 買通項目經理,給你時間重構
厲害的人不是跟著面試官的問題走,而是把他帶到你的節奏上來
補充一下,還有一般都會問你在項目中遇到最難的問題是什麼,怎麼解決的?或者是問什麼感覺最有成就?
又得換面試題庫了。
推薦閱讀:
※如何評價微軟的 AoW 技術(Android on Windows)?
※各大主流的移動或者桌面操作系統的默認中英文字體都是什麼?各有什麼優缺點(就主觀而言)?
※除了華為,還有哪些國產手機是自帶谷歌服務框架的?
※安卓應用的 UI 潮流是如何產生的?
※優化 listview 有哪些方法?