1. 程式人生 > 其它 >【面試必備】一個小例子徹底搞懂Android的MVP模式到底是什麼?逆襲面經分享

【面試必備】一個小例子徹底搞懂Android的MVP模式到底是什麼?逆襲面經分享

前言

1、主動學習,努力提升,與社會發展同行

在職場上工作的年限越長,就越容易形成定勢思維,這也許就是思維僵勢的影響。這種習慣性思維正是縮小中年人生存空間的一大原因。

隨著新行業、新技術的出現,要想不被社會淘汰,就必須具備迭代思維,主動突破思維惰性,接受新知識,讓自己遠離職場“老油條”的稱號。這種努力付出只會讓你的路越走越寬。

2、融入圈子,建立人脈資源

人想要提升自己,就要逼迫自己融入想要進入的圈子,這樣你才能認識不同的人,建立自己想要的人脈資源。

3、提高自律,擁有健康

健康是革命的本錢。很多成功人士都明白健康的重要性,所以不管自己多忙,都會不忘記健身。馬雲天天打太極、王石每天跑步。

雖然你現在已經35歲或正在向35歲走來,但只要你不自我放,堅持做好這三件事,相信你不會遇到所謂的中年危機,更不會找不到工作。

一、Android效能優化的方面

針對Android的效能優化,主要有以下幾個有效的優化方法:

1.佈局優化

2.繪製優化

3.記憶體洩漏優化

4.響應速度優化

5.ListView/RecycleView及Bitmap優化

6.執行緒優化

7.其他效能優化的建議

下面我們具體來介紹關於以上這幾個方面優化的具體思路及解決方案。

二、佈局優化

關於佈局優化的思想很簡單,就是儘量減少佈局檔案的層級。這個道理很淺顯,佈局中的層級少了,就意味著Android繪製時的工作量少了,那麼程式的效能自然就提高了。

如何進行佈局優化?

  • ①刪除佈局中無用的控制元件和層次,其次有選擇地使用效能比較低的ViewGroup。

關於有選擇地使用效能比較低的ViewGroup,這就需要我們開發就實際靈活選擇了。

例如:如果佈局中既可以使用LinearLayout也可以使用RelativeLayout,那麼就採用LinearLayout,這是因為RelativeLayout的功能比較複雜,它的佈局過程需要花費更多的CPU時間。FrameLayout和LinearLayout一樣都是一種簡單高效的ViewGroup,因此可以考慮使用它們,但是很多時候單純通過一個LinearLayout或者FrameLayout無法實現產品效果,需要通過巢狀的方式來完成。這種情況下還是建議採用RelativeLayout,因為ViewGroup的巢狀就相當於增加了佈局的層級,同樣會降低程式的效能。

  • ②採用標籤,標籤,ViewStub。

標籤主要用於佈局重用。 標籤一般和配合使用,可以降低減少佈局的層級。 ViewStub提供了按需載入的功能,當需要時才會將ViewStub中的佈局載入到記憶體,提高了程式初始化效率。

③避免多度繪製

過度繪製(Overdraw)描述的是螢幕上的某個畫素在同一幀的時間內被繪製了多次。在多層次重疊的 UI 結構裡面,如果不可見的 UI 也在做繪製的操作,會導致某些畫素區域被繪製了多次,同時也會浪費大量的 CPU 以及 GPU 資源。 如下所示,有些部分在佈局時,會被重複繪製。
關於過度繪製產生的一般場景及解決方案,參考:[Android 過度繪製優化]

三、繪製優化 繪製優化是指

View的onDraw方法要避免執行大量的操作,

這主要體現在兩個方面:

①onDraw中不要建立新的區域性物件。** 因為onDraw方法可能會被頻繁呼叫,這樣就會在一瞬間產生大量的臨時物件,這不僅佔用了過多的記憶體而且還會導致系統更加頻繁gc,降低了程式的執行效率。

②onDraw方法中不要做耗時的任務,也不能執行成千上萬次的迴圈操作,儘管每次迴圈都很輕量級,但是大量的迴圈仍然十分搶佔CPU的時間片,這會造成View的繪製過程不流暢。

按照Google官方給出的效能優化典範中的標準,View的繪製頻率保證60fps是最佳的,這就要求每幀繪製時間不超過16ms(16ms = 1000/60),雖然程式很難保證16ms這個時間,但是儘量降低onDraw方法中的複雜度總是切實有效的。

四、記憶體洩漏優化

記憶體洩漏是開發過程中的一個需要重視的問題,但是由於記憶體洩露問題對開發人員的經驗和開發意識有較高的要求,因此也是開發人員最容易犯的錯誤之一。

記憶體洩露的優化分為兩個方面:

①在開發過程中避免寫出有記憶體洩漏的程式碼

②通過一些分析工具比如MAT來找出潛在的記憶體洩露,然後解決。

對應於兩種不同情況,一個是瞭解記憶體洩漏的可能場景以及如何規避,二是怎麼查詢記憶體洩漏。

1.那麼我們就先了解什麼是記憶體洩漏?

這樣我們才能知道如何避免。

大家都知道,java是有垃圾回收機制的,這使得java程式設計師比C++程式設計師輕鬆了許多,儲存申請了,不用心心念念要加一句釋放,java虛擬機器會派出一些回收執行緒兢兢業業不定時地回收那些不再被需要的記憶體空間(注意回收的不是物件本身,而是物件佔據的記憶體空間)。

Q1:什麼叫不再被需要的記憶體空間?

答:Java沒有指標,全憑引用來和物件進行關聯,通過引用來操作物件。如果一個物件沒有與任何引用關聯,那麼這個物件也就不太可能被使用到了,回收器便是把這些“無任何引用的物件”作為目標,回收了它們佔據的記憶體空間。

Q2:如何分辨為物件無引用?

答:2種方法 引用計數法直接計數,簡單高效,Python便是採用該方法。但是如果出現 兩個物件相互引用,即使它們都無法被外界訪問到,計數器不為0它們也始終不會被回收。為了解決該問題,java採用的是b方法。

可達性分析法這個方法設定了一系列的“GC Roots”物件作為索引起點,如果一個物件 與起點物件之間均無可達路徑,那麼這個不可達的物件就會成為回收物件。這種方法處理 兩個物件相互引用的問題,如果兩個物件均沒有外部引用,會被判斷為不可達物件進而被回收(如下圖)。

Q3:有了回收機制,放心大膽用不會有記憶體洩漏?

答:答案當然是No! 雖然垃圾回收器會幫我們幹掉大部分無用的記憶體空間,但是對於還保持著引用,但邏輯上已經不會再用到的物件,垃圾回收器不會回收它們。

這些物件積累在記憶體中,直到程式結束,就是我們所說的“記憶體洩漏”。 當然了,使用者對單次的記憶體洩漏並沒有什麼感知,但當洩漏積累到記憶體都被消耗完,就會導致卡頓,崩潰。 下面這張圖可以幫助我們更好地理解物件的狀態,以及記憶體洩漏的情況

左邊未引用的物件是會被GC回收的,右邊被引用的物件不會被GC回收,但是未使用的物件中除了未引用的物件,還包括已被引用的一部分物件,那麼記憶體洩漏久發生這部分已被引用但未使用的物件。

2.Android一般在什麼情況下會出現記憶體洩漏?

①集合類洩漏
②單例/靜態變數造成的記憶體洩漏
③匿名內部類/非靜態內部類
④資源未關閉造成的記憶體洩漏 大概可以分為以上幾類,還有一些經常會聽到的Hanlder,AsyncTask引起記憶體洩漏,都屬於上述③中的情況。 那麼上述四種情況是怎麼造成的記憶體洩漏,具體是什麼原因,以及Android中一些知名的引起記憶體洩漏的原因,以及解決方法是怎麼樣的?

3.Android怎麼分析記憶體洩漏?

上面介紹了記憶體洩漏的場景,對應的有一些解決方案。 那麼在記憶體洩漏已經發生的情況下,我們該如何解決呢? 我們可以通過MAT(Memory Analyzer Tool),或者 LeakCanary來檢測Android中的記憶體洩漏。

五、響應速度優化

響應速度優化的核心思想就是避免在主執行緒中做耗時操作

如果有耗時操作,可以開啟子執行緒執行,即採用非同步的方式來執行耗時操作。 如果在主執行緒中做太多事情,會導致Activity啟動時出現黑屏現象,甚至ANR。Android規定,Activity如果5秒鐘之內無法響應螢幕觸控事件或者鍵盤輸入事件就會出現ANR,而BroadcastReceiver如果10秒鐘之內還未執行完操作也會出現ANR。

為了避免ANR,可以開啟子執行緒執行耗時操作,但是子執行緒不能更新UI,所以需要子執行緒與主執行緒進行通訊來解決子執行緒執行耗時任務後,通知主執行緒更新UI的場景。關於這部分,需要掌握Handler訊息機制,AsyncTask,IntentService等內容。

然而,在實際開發中,ANR仍然不可避免的發生了,而且很難從程式碼上發現,這時候就要用到ANR日誌分析。當一個程序發生了ANR之後,系統會在/data/anr目錄下建立一個檔案traces.txt,通過分析這個檔案就能定位出ANR的原因。

六、ListView/RecycleView及Bitmap優化

ListView/RecycleView的優化思想主要從以下幾個方面入手:
①使用ViewHolder模式來提高效率
②非同步載入:耗時的操作放在非同步執行緒中
③ListView/RecycleView的滑動時停止載入和分頁載入 具體優化建議及詳情,Bitmap優化 主要是對載入圖片進行壓縮,避免載入圖片多大導致OOM出現。

七、執行緒優化

執行緒優化的思想就是採用執行緒池,避免程式中存在大量的Thread。執行緒池可以重用內部的執行緒,從而避免了執行緒的建立和銷燬鎖帶來的效能開銷,同時執行緒池還能有效地控制執行緒池的最大並法術,避免大量的執行緒因互相搶佔系統資源從而導致阻塞現象的發生。因此在實際開發中,儘量採用執行緒池,而不是每次都要建立一個Thread物件。

八、其他效能優化建議

①避免過度的建立物件
②不要過度使用列舉,列舉佔用的記憶體空間要比整型大
③常量請使用static final來修飾
④使用一些Android特有的資料結構,比如SparseArray和Pair等
⑤適當採用軟引用和弱引用
⑥採用記憶體快取和磁碟快取
⑦儘量採用靜態內部類,這樣可以避免潛在的由於內部類而導致的記憶體洩漏。

以上是關於Android效能優化方面,我們一些入手點。從這些方面,我們可以在平時的開發中注意,避免類似錯誤,提高Android程式的效能,但是其中一些方面的要求則需要我們不斷的學習,以及平時良好的意識與習慣。由於自己開發經驗幾乎為0,沒辦法根據實際經驗來說明,只能寫下這篇文章來提醒自己以後開發的時候需要注意和培養的地方。

如何做好面試突擊,規劃學習方向?

面試題集可以幫助你查漏補缺,有方向有針對性的學習,為之後進大廠做準備。但是如果你僅僅是看一遍,而不去學習和深究。那麼這份面試題對你的幫助會很有限。最終還是要靠資深技術水平說話。

網上學習 Android的資料一大堆,但如果學到的知識不成體系,遇到問題時只是淺嘗輒止,不再深入研究,那麼很難做到真正的技術提升。建議先制定學習計劃,根據學習計劃把知識點關聯起來,形成一個系統化的知識體系。

學習方向很容易規劃,但是如果只通過碎片化的學習,對自己的提升是很慢的。

同時我還蒐集整理2020年位元組跳動,以及騰訊,阿里,華為,小米等公司的面試題,把面試的要求和技術點梳理成一份大而全的“ Android架構師”面試 Xmind(實際上比預期多花了不少精力),包含知識脈絡 + 分支細節

在搭建這些技術框架的時候,還整理了系統的高階進階教程,會比自己碎片化學習效果強太多。

點選:《Android架構視訊+BAT面試專題PDF+學習筆記》即可免費獲取~

網上學習 Android的資料一大堆,但如果學到的知識不成體系,遇到問題時只是淺嘗輒止,不再深入研究,那麼很難做到真正的技術提升。希望這份系統化的技術體系對大家有一個方向參考。