android開發中stackoverflowerror錯誤執行個體分析
一、概述
<a target="_blank"></a>
我在一個複雜的layout嵌套較多的android界面,碰到了java.lang.stackoverflowerror這個fatal exception,app程式crash退出。這個錯誤出現的比較奇怪,在我做技術調研的時候,這個界面是放在單獨的一個程式中展示的,工作很正常,沒有出現這個嚴重錯誤,當将其嵌入到一個activitygroup後才報錯。
android sdk中對該錯誤的出現的場景描述為:由于棧調用的層次太多,超過了虛拟器dalvik的最大限制(作為一個虛拟器參數,可定制)導緻的。當程式編寫錯誤導緻無限遞歸調用時會觸發,此外程式正确但是遞歸調用的層次過深也會觸發。
結合我的界面的情況,在單獨程式中運作時沒有問題,則說明不存在死循環的無限遞歸錯誤。觀察該界面的內建情況,發現為了tab頁實作,該界面在顯示時,被兩個activitygroup嵌套,增加了6層顯式父layout。而因為該界面複雜,設計時,list_header view的layout深度為5層,而list_item的深度則為6層。原因定位為界面嵌套層次過深。
二、解決方法
解決嵌套過深的基本思路是在實作同樣的效果的前提下減少界面的layout深度。在我将list_header view layout深度由5層精簡為3層,list_item 深度由6層減少為4層後,該錯誤被解決。具體的方法有:
1) 多用relativelayout的各種布局屬性來完成布局,而避免過多使用嵌套layout來實作。
2) 占位或填充剩餘空間的元素多用view,避免使用layout等viewgroup。
總結下,從實際的資料來看,設計中layout嵌套深度超過10層,就應該考慮下優化了,否則就會出現java.lang.stackoverflowerror的crash了。
三、錯誤詳細日志
e/androidruntime( 5196): fatal exception: main
e/androidruntime( 5196): java.lang.stackoverflowerror
e/androidruntime( 5196): at android.graphics.paint.measuretext(paint.java:1057)
e/androidruntime( 5196): at android.text.styled.drawdirectionalrun(styled.java:267)
e/androidruntime( 5196): at android.text.styled.measuretext(styled.java:430)
e/androidruntime( 5196): at android.text.layout.measuretext(layout.java:1655)
e/androidruntime( 5196): at android.text.layout.getlinemax(layout.java:689)
e/androidruntime( 5196): at android.text.layout.draw(layout.java:340)
e/androidruntime( 5196): at android.widget.textview.ondraw(textview.java:4050)
e/androidruntime( 5196): at android.view.view.draw(view.java:6740)
e/androidruntime( 5196): at android.view.viewgroup.drawchild(viewgroup.java:1640)
e/androidruntime( 5196): at android.view.viewgroup.dispatchdraw(viewgroup.java:1367)
e/androidruntime( 5196): at android.view.view.draw(view.java:6743)
e/androidruntime( 5196): at android.view.viewgroup.drawchild(viewgroup.java:1638)
e/androidruntime( 5196): at android.view.view.builddrawingcache(view.java:6502)
e/androidruntime( 5196): at android.view.view.getdrawingcache(view.java:6288)
e/androidruntime( 5196): at android.view.viewgroup.drawchild(viewgroup.java:1565)
e/androidruntime( 5196): at android.widget.abslistview.dispatchdraw(abslistview.java:1365)
e/androidruntime( 5196): at android.widget.listview.dispatchdraw(listview.java:3046)
e/androidruntime( 5196): at android.view.view.draw(view.java:6846)
e/androidruntime( 5196): at android.widget.abslistview.draw(abslistview.java:2257)
e/androidruntime( 5196): at android.widget.framelayout.draw(framelayout.java:352)
e/androidruntime( 5196): at com.android.internal.policy.impl.phonewindow$decorview.draw(phonewindow.java:1842)
e/androidruntime( 5196): at android.view.viewroot.draw(viewroot.java:1407)
e/androidruntime( 5196): at
w/activitymanager( 71): force finishing activity com.baidu.test/.clouddemactivity
w/windowmanager( 71): no window to dispatch pointer action 1