最近出現了一個讓人抓狂的問題。java
如今的項目中,製做了一個界面很是複雜。Fragment中嵌套下拉刷新的Listviewandroid
這樣一個佈局,在3.0以上的手機上都表現良好問題!可是在2.x的比較弱爆的手機上會出現canvas
Android 2.3 I'm getting a StackOverflowError when the layout is drawn:ide
at android.view.View.draw(View.java:6880)
at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
at android.view.View.draw(View.java:6883)
at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
...佈局
棧溢出問題。各類谷歌以後發現,不少人在2.x上也會有這個問題,究其緣由就是View的層次嵌套過多,而2.x上Android給UI主線程分配了大概8KB的棧空間。大概最多隻會有60到80層的stack frame。這個空間存儲不了個人這個佈局,後分析發現,因爲最裏層嵌套了Listview ,每一個Item都有很深,並且每一個Item在不斷的進行着重繪。最終致使了2.x機型的棧溢出問題。post
大部分的方法就是優化佈局,減小嵌套。優化
和網上說的同樣,接下來就是不斷的優化,能減極簡。可是到最後優化到評論的listview的層次大概爲16層,在部分的android 2.x上依舊報這個問題。若是要繼續優化下去,就得去掉fragment。由於在觀看佈局時發現,v4包的fragment會在最外層添加一個NosavestateFramelayout。而我用到的是Fragment中嵌套了Fragment,這就致使無緣無故多了兩層。若是要保持我如今的佈局就得考慮去掉Fragment,所有改用View。可是項目緊張,根原本不及切換過來。因而只能進行降級。spa
固然還有一些比較不太優雅的解決方式:線程
好比在你最深層次容易爆崩潰的View中,把全部的View都重寫Draw方法blog
private Handler mHandler =new Handler(); @Overridepublicvoid draw(Canvas canvas){ try{super.draw(canvas); }catch(StackOverflowError e){ mHandler.postDelayed(newRunnable(){publicvoid run(){ invalidate(); } },1); } }
雖然最好的方法仍然是去優化你的佈局,解嵌套,不只能加快頁面渲染速度,還能解決此問題。可是實在是沒有任何可優化的時候,只能先使用這種比較髒的方式。我最後使用的是進行了降級,由於項目緊張,並且不容有失,因此降級成了最保險的選擇。對於2.x系統這種強加的限制,表示真的是太蛋疼了!
The stack size of UI thread in Android 2.x is 12KB and in Android 4.x is 16KB. These 4KB make all the difference - since the above layout crashes on 2.x with StackOverflow.
對於嵌套過深的地方,尤爲當有listview時,必定要注意,能去fragment就去掉fragment!儘可能直接換用ViewGroup