感覺這是一個很有意思的工具,可以檢測UI線程處理每個message時間删壮。如果時間長了贪绘,那么就發(fā)個通知,通知開發(fā)者哪里可能存在問題央碟。原理并不難税灌,不過作者能想出來這種方法來檢測手機app的一些性能問題,還是挺有心的亿虽,應該給作者點個贊菱涤。
開源庫的地址是 戳這里
哪些卡頓檢查不出來
首先說下這個工具只能檢測一些性能問題÷迕悖卡頓的問題不只是因為message的執(zhí)行時間過長粘秆。比如:界面的渲染是在Render Thread線程。主線程會把view#draw()方法的指令解析成GPU能讀懂的指令收毫,然后傳給Render Thread線程攻走。 GPU再根據(jù)這些指令進行渲染。繪制是一個很復雜的過程此再。雖然有了Render Thread線程來做渲染工作昔搂,大部分時間Render Thread 和主線程是并發(fā)進行的,但是還是會有一個點 兩個線程是互相依賴的输拇。他們需要相互等待來交換數(shù)據(jù)摘符,以便將數(shù)據(jù)寫入到 back buffer中。back buffer是從SurfaceFlinger 服務的buffer隊列請求來的。當把渲染的數(shù)據(jù)寫到back buffer后逛裤,會返回給SurfaceFlinger 服務的buffer隊列蠢古。SurfaceFlinger會根據(jù)硬件屏幕刷新時鐘Async來把buffer(這里叫frame buffer)給到android系統(tǒng)中進行屏幕展示。這里的要展示的frame buffer來自于back buffer别凹。所以如果繪制不及時(>16ms), back buffer在16ms內沒有裝載完畢。那么SurfaceFlinger只能把之前的back buffer當成frame buffer提交給屏幕進程呈現(xiàn)洽糟。因此卡頓就產生了炉菲。
因此,繪制不及時有很多種坤溃。比如上面說的Render Thread線程繪制了一個很復雜的view(比如給view添加蒙層拍霜,就會導致繪制的復雜),因為主線程與Render Thread線程存在依賴薪介,那么主線程需要等待祠饺,導致back buffer不能完成,進而產生卡頓汁政。這時候UI線程中處理msg的時間并不長道偷,只是一直在block等待。這種卡頓AndroidPerformanceMonitor并不能處理记劈。
原理分析
原理就不貼代碼了勺鸦,幾句話就能說完。貼代碼反而影響問題的闡述目木。
我們知道换途,主線程的Looper工作在一個for循環(huán)中,每次從隊列中拿到一個meesage進行處理刽射。在處理每一個message時军拟,在開始處理,到處理完成都會使用Printer來打印一些東西誓禁。開始時打有赶ⅰ:
'' logging.println(">>>>> Dispatching to " + msg.target + " " +
'' msg.callback + ": " + msg.what);
結束時打印:
'' logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
這個Printer是Looper的mLogging成員變量现横,我們可以設置漓拾。原理就在這里。我們可以設置一個自定義的Printer戒祠。重寫Printer的println(String)方法骇两。在重寫的println(String)方法中判斷,如果參數(shù)string中包含“Dispatching to”姜盈,那么就往HandleThread線程的隊列中添加一個延時300ms的runnable低千,runnable中處理卡頓信息的邏輯。如果判斷參數(shù)string中包含“Finished“,那么如果HandleThread線程的隊列 中的runnable還在示血,就清除這個runnable棋傍。即,說明這個message執(zhí)行完還不到300ms难审,那么就認為處理這個message沒有發(fā)生卡頓瘫拣。當然如果打印”Finished“時,與”Dispatching“的時間差已經大于了300ms告喊,那么runnable便已經執(zhí)行了處理卡頓信息的邏輯麸拄。
大致原理就是這樣。