“猿猿,你看啊,我從這裏進去詳情頁,然後再點多幾個頁面的話,我整部手機就卡死了,完全動不了啊,你看怎麼解決一下啊!”程序猿白眼了一下突然坐在他旁邊的產品汪,“之前需求會的時候我就說了這樣的操作肯定是有問題的啊,一直點一直點都能進去,無限循環了啊!手機再大的內存都會佔用了啊!就是不聽,還說這樣的操作灰常正常喔!”,“這是很正的一個邏輯啊,有得點擊肯定能進去下一個頁面了啊...”產品汪又在噼裏啪啦的講着大道理...
“行行行,你就別說了,好嗎?下來我先看看是什麼原因”,程序猿不耐煩的說,“這就對了嘛,我看好你哦!”產品汪邊說邊摸了下程序猿的後背...
2故事的開始
故事的開始是在一個星期前的需求會上,產品汪跟程序猿在爭吵着一個頁面邏輯的問題,一個新聞詳情頁裏面含有推薦的帖子或者新聞等東西,點擊可以進去另一個頁面,並且是無限循環的狀態,一直可以進到下一個頁面。
程序猿一直堅持這樣的邏輯是非常不合理的,然而誰叫程序猿一直都是弱勢羣體,只能忍氣吞聲的接受這一殘忍的事實,做唄。
PS:其實從產品經理的角度看,這個是非常正常的一個操作,有推薦自然會進去新的頁面,返回當然還是回到上一個頁面,這是一個非常合乎其理的設計啊。
3故事的經過其實,程序猿心裏早就知道是什麼原因了,只是之前的時間一直在趕項目,沒有時間優化,因爲這事還跟產品汪說了幾次,說了要有一個空檔期給客戶端優化,還一直不安排,一直說了要讓產品、UI、服務器先行,客戶端緊隨起步,那樣就有更好的空檔期進行優化,就是不聽,現在好了,終於有時間優化優化了。
PS:敏捷開發,小步快跑!其實很多研發還是很難掌握敏捷開發的,團隊必須要有很強的協作和應變能力。
趁這個機會,把整個項目一起優化優化,程序猿心裏還是有種變態的開心的。
之前已經大範圍的進行了UI的優化了,還會出現卡死的情況,到底是什麼原因呢?程序猿陷入沉思...
突然靈光一閃----內存!程序猿欣喜若狂,急忙把手機連接上,打開APP。
先來模擬定位一下到底是哪裏出現問題吧,打開Android Profiler(Android Studio 3.0.1自帶工具),點點點...一直重複操作進入到新的頁面,我去,內存一直在升高啊,並且我退出了當前頁面,也沒有一點內存回收的跡象啊...
這肯定是內存泄漏了啊!回收不了啊!長期積累肯定會造成APP卡頓,乃至卡死呀,並且會出現崩潰(OOM)啊!
想想爲什麼會造成內存泄漏了呢?
注:造成內存泄露就是一個對象持有超過自己生命週期以外的對象強引用導致該對象無法被正常回收。
好吧,既然知道問題所在,那就對症下藥吧。
首先,要知道在什麼情況下會出現內存泄漏,然後,我們才能解決問題。
1、Context
不要對一個Activity Context保持長生命週期的引用。儘量在可以使用ApplicationContext代替Context的地方進行替換,比如一個單例需要傳入Context,則可以使用ApplicationContext進行替代,這裏就涉及到了不同Context的使用域了。
2、非靜態內部類的靜態實例
一個類中如果你不能夠控制它其中內部類的生命週期(譬如Handler),則儘量使用靜態類和弱引用來處理。
3、線程未終止造成的內存泄露
如在Activity中創建了一個Thread,如在退出Activity時線程還在跑,必須要結束線程。
4、對象的註冊與反註冊沒有成對出現
如註冊廣播接收器、註冊觀察者等。
5、創建與關閉沒有成對出現造成的泄露
如Cursor必須關閉,WebView必須銷燬,流等I/O對象必須關閉。
6、Bitmap
在不使用的時候,記得要手動回收Bitmap,在加載Bitmap的時候一定一定要按需加載進行壓縮處理並且重複利用,有些時候還可以使用弱引用替代強引用。
7、ListView的優化(這個不是在UI佈局優化那裏說了嗎?)。
8、儘量使用線程池來替代多線程,節約內存並且能節省CPU的使用率。
9、最重要的一點!!!不斷優化自己的代碼,時刻保持優良的習慣,減少冗餘,進行編譯打包等優化對齊處理,避免類加載時浪費內存。
不錯,思路已經非常清晰了,一步一步來,開始動手檢查代碼優化代碼了。
注:適當時候可以結合一些工具進行持續優化,如LeakCanary,還有AS的工具Android Profiler,Eclipse的DDMS-Heap,MAT。
4故事的尾聲“來來來,我們歡迎Android開發組的猿猿爲我們分享一下如何對APP進行調優的,並且給我們介紹一下那些調優工具是怎麼使用的,我們一起來好好學習一下!”產品汪拍着手笑嘻嘻的說道。
To Be Continue...