天天看點

Android開發中StackOverflowError

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

繼續閱讀