在過去幾年間,移動應用以雷霆之勢席卷全球。我們在工作和休閑時間中使用互聯網的方式,已經隨著移動應用的前進腳步發生了變革。在開發應用的時候,人們也開始考慮“移動優先”的做法。我們正在面對全新一代的移動設備,諸如可穿戴設備或眾多移動配件——正是它們構成了“萬物互聯”的世界。我們將面對全新的用戶界面,通過它們數據展示及指令接收處理。同時,我們還將看到,越來越多的公司將真正地踐行“移動優先”的思路。而在未來數年中,這一切都將影響我們設計、開發和測試軟件的方式。
把一個客戶端做得穩定、無奔潰、流暢,是寫客戶端朋友的夢想,但是,我們面臨的結果往往是不如人意的。天下武功,唯快不破。很多公司都信奉這個教條。恨不得把app開發周期壓縮到最低,這就導致了開發中隱藏了很多問題。有點經驗的工程師草率的優化一下,更糟的情況是那些沒有經驗的工程師甚至不會對app進行任何優化,這將會使情況變的更糟。
十年前,移動設備的硬件資源是非常有限的.甚至連浮點數都是被禁止的.因為浮點數能導致計算的速度變慢。科技發展如此迅速的今天,硬件很大程度上可以彌補軟件的短板。但是硬件的進步終究無法掩飾軟件的不足,這也是寫這篇文章的初心。
移動端關注要點
在程序開發中,測試是必不可少的。移動端測試按大的類型劃分可以分為白盒測試和黑盒測試。
白盒測試一般是由開發人員使用編碼的方式進行。測試者需要接觸程序的內部代碼;而黑盒測試可以在不知道程序內部結構和代碼的情況下進行。
下面是主要的測試流程了:
冒煙測試:在軟件測試中,冒煙測試是指快速驗證APP的主要功能(例如:微信的登陸、退出、發消息等功能) 。如果沒有發現問題,再進行更加深入的測試工作;如果發現有問題,就說明APP有重大缺陷。
功能測試:功能測試也叫行為測試,需要根據測試用例來驗證應用預期的功能有沒有實現。
自由探索式測試:嘗試邊界條件、輸入特殊符號、異常網絡環境、突然中斷程序等操作 。功能測試的目的是驗證正常的功能有沒有實現,而自由探索測試的目的就是為了試試應用在極端的操作下會不會出現問題。探索式測試就是要找到能讓應用出錯的操作。
回歸測試:對之前使用我們的服務測試過的應用,將案例復測一遍。
移動端關注的一些指標
運行多少小時不崩潰;
多次打開頁面,控制崩潰率;
界面優化,如何才能讓用戶不急躁、不煩躁;
服務器沒有返回數據,是否會導致奔潰;
網絡不好,數據來的太慢,界面是否不流暢;
從數據庫讀的數據太慢如何解決等。
移動端界面應該有自己的邏輯,需要網絡數據的地方,應該有默認值,這樣在網絡數據沒有返回的情況下,讓用戶有數據可以看到。收到的網絡數據應該是通過某種方式刷新到界面,而不是等到數據返回才刷新頁面。當沒有網絡數據的時候,界面應該可以自成一體,走的通流程,不強依賴網絡數據。
在弱網模式下調試是我們必備的功力,因為我們要考慮用戶的實施環境通常都不會很好。把經常使用的數據,存到緩存,提高APP的運行效率、界面流程度。同時,我們需要具備收集奔潰日志的功能,這樣才能更好的減少崩潰,提高用戶體驗。
界面卡頓產生的原因和解決方案
iOS界面處理是在主線程下進行的,系統圖形服務通過 CADisplayLink 等機制通知 App,App 主線程開始在 CPU 中計算顯示內容,比如視圖的創建、布局計算、圖片解碼、文本繪制等。隨后 CPU 會將計算好的內容提交到 GPU 去,由 GPU 進行變換、合成、渲染。隨后 GPU 會把渲染結果提交到幀緩沖區去,等待下一次刷新信號到來時顯示到屏幕上。顯示器通常以固定頻率進行刷新,如果在一個刷新時間內,CPU 或者 GPU 沒有完成內容提交,則那一幀就會被丟棄,等待下一次機會再顯示,而這時顯示屏會保留之前的內容不變。這就是界面卡頓的原因。CPU 和 GPU 不論哪個阻礙了顯示流程,都會造成掉幀現象。
CPU 造成的資源消耗有以下幾種:
- 對象創建
- 對象調整
- 對象銷毀
- 布局計算
- Autolayout
- 文本計算
- 文本渲染
- 圖片的繪制和解碼
GPU 資源消耗有下面幾種情況:
- 紋理的渲染
- 視圖的混合 (Composing)
- 圖形的生成等
具體可以參考這篇文章
用 Instruments 來檢驗你的app
時間事件查看器-Time Profiler
在xcode的菜單中選擇 product->Profile
我們會看到下面的界面:
點擊Time Profiler進入。
下面我們來深究如下的控制面板:
以下介紹下配置選項:
- Separate by Thread: 每個線程應該分開考慮。只有這樣你才能揪出那些大量占用CPU的"重"線程。
- Invert Call Tree: 從上倒下跟蹤堆棧,這意味著你看到的表中的方法,將已從第0幀開始取樣,這通常你是想要的,只有這樣你才能看到CPU中話費時間最深的方法.也就是說FuncA{FunB{FunC}} 勾選此項后堆棧以C->B-A 把調用層級最深的C顯示在最外面。
- Hide System Libraries: 勾選此項你會顯示你app的代碼,這是非常有用的. 因為通常你只關心cpu花在自己代碼上的時間不是系統上的。
- Flatten Recursion: 遞歸函數, 每個堆棧跟蹤一個條目。
- Top Functions: 一個函數花費的時間直接在該函數中的總和,以及在函數調用該函數所花費的時間的總時間。因此,如果函數A調用B,那么A的時間報告在A花費的時間加上B.花費的時間,這非常真有用,因為它可以讓你每次下到調用堆棧時挑最大的時間數字,歸零在你最耗時的方法。
找到Detail面板里最耗時的進程,點擊進去可以看到代碼,觀察是否有異,如此便可逐步優化應用的運行效果了。
修改好后,在儀器重新運行該應用程序Product—Profile(或?I-記住,這些快捷鍵真的會為您節省一些時間)。
分配工具
這個時候你會發現兩個曲目。一個叫(分配)Allocations,以及一個被稱為VM Tracker(虛擬機跟蹤)。
內存泄漏有兩種泄漏。第一個是真正的內存泄漏,一個對象尚未被釋放,但是不再被引用的了。因此,存儲器不能被重新使用。第二類泄漏是比較麻煩一些。這就是所謂的“無界內存增長”。這發生在內存繼續分配,并永遠不會有機會被釋放。如果永遠這樣下去你的程序占用的內存會無限大,當超過一定內存的話 會被系統的看門狗給kill掉。
內存警告是ios處理app最好的方式,尤其是在內存越來越吃緊的時候,你需要清除一些內存。內存一直增長其實也不一定是你的代碼出了問題,也有可能是UIKit 系統框架本身導致的。
自己動手觀察下,一切自然明了。
內存泄露
這一類泄漏是前面提到的 - 當一個對象不再被引用時出現的那種,檢測泄漏可以理解為一個很復雜的事情,但泄漏的工具記得已分配的所有對象,通過定期掃描每個對象以確定是否有任何不能從任何其他對象訪問的。
關閉儀器,回到Xcode和選擇Product->Profile
點擊進入,運行:
自己動手嘗試下,找到右邊面板里,如果有黑色標識的方法,進入看看。學習就是多嘗試。
篇幅有限,更多的內容我們下次再聊。