Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/210.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
android UI线程堆栈大小限制是什么?如何克服它?_Android - Fatal编程技术网

android UI线程堆栈大小限制是什么?如何克服它?

android UI线程堆栈大小限制是什么?如何克服它?,android,Android,在绘制视图层次结构时,我得到了java.lang.StackOverflowers错误: 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 a

在绘制视图层次结构时,我得到了java.lang.StackOverflowers错误:

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)
...
指出我的视图层次太深,Android无法处理。事实上,使用层次查看器,我可以看到我最长的嵌套是19个视图(!)

我的应用程序看起来有点像Google Play store应用程序(带有滑动标签)。每个选项卡都是片段视图寻呼机中的嵌套片段-使用v4支持和HoloEverywhere。显然,这就是我的等级制度变得有点疯狂的原因

我的问题是:

  • 真正的堆栈大小限制是多少?我发现没有办法测量UI线程的堆栈大小。网上有些传言说8KB,但有没有办法在一些样本设备上精确测量这个值

  • 堆栈大小限制是否随操作系统版本而改变?相同的层次结构不会在4.0.3设备上崩溃,但会在2.3.3设备(相同的硬件)上崩溃。为什么呢

  • 除了手动优化层次结构之外,还有其他解决方案吗?我发现没有办法增加UI线程小得可笑的堆栈。抱歉,60-100堆栈帧限制是个笑话

  • 假设在#3上没有奇迹般的解决方案,那么对于应该在哪里进行核心层次结构优化,有什么建议吗

  • 疯狂的想法-我注意到每个视图层都添加了大约3个函数调用(view.draw、ViewGroup.dispatchDraw、ViewGroup.drawChild)。也许我可以制作自己的视图组实现(自定义布局),以便在draw()期间减少对堆栈的浪费


  • 我不知道堆栈大小限制是什么,坦率地说,我不认为搜索它会有多大用处。正如你的第二个建议所暗示的,这很可能取决于设备上有什么版本的Android和/或Dalvik VM

    至于优化布局,一些选项包括:

  • 使用RelativeLayout而不是嵌套视图组,特别是线性布局中的线性布局,有助于展平视图层次。这不是一个万能的解决方案;事实上,嵌套RelativeLayout可能会影响性能(因为RelativeLayout总是
    measure()
    s两次,所以嵌套它们会对度量阶段产生指数效应)

  • 根据第五个问题,使用自定义视图/视图组。我听说有几个应用程序可以做到这一点,我认为甚至谷歌的一些应用程序也可以做到这一点

  • 如果您在视图层次结构中发现任何无用的子级,您可以尝试在一些布局中使用
    标记(但是我自己还没有发现它们有很多用途)

  • 我相信主线程的堆栈是由JVM控制的——在Android的例子中是Dalvik JVM。如果我没有弄错的话,可以在
    #define kDefaultStackSize
    下的
    dalvik/vm/Thread.h
    中找到相关常量

    通过dalvik源历史浏览堆栈大小:

    • API 3()=8KB

    • API 4-10(-)=12KB

    • API 14-17(-)=16KB

    那么您可以有多少嵌套视图:

    不可能准确地说。假设堆栈大小如上所述,这完全取决于最深嵌套中有多少函数调用(以及每个函数使用多少变量,等等)。问题似乎出在绘制视图时,首先是
    android.view.ViewRoot.draw()
    。每一个视图都会召唤出它的孩子,它会像你最深的巢穴一样深入

    我将至少对出现在上述所有边界组中的装置进行经验测试。使用仿真器似乎可以给出准确的结果(尽管我只是将本机x86仿真器与实际设备进行了比较)


    请记住,对实际小部件/布局实现方式的优化也可能会影响这一点。话虽如此,我相信大多数堆栈空间都被添加了大约3个嵌套函数调用的每个布局层次结构占用了:
    draw()
    ->
    dispatchDraw()
    ->
    drawChild()
    ,这种设计与2.3-4.2相比没有太大变化。

    疯狂的想法5-可能没有那么疯狂。我向你解释这个理论,你试着用一些方法来实现它。假设我们有3个嵌套视图A>B>C。不要将C嵌套在B中,而是将其嵌套在D中(一些不相关的视图),当B要自己绘制时,他需要调用B.draw()。当然,您可能遇到的问题是糟糕的布局。但是有可能找到解决办法。

    更好地解释我的疯狂想法5。我并不是说这是个好主意:)但我想澄清一下如何做到这一点

    我们将为基本布局(LinearLayout、FrameLayout、RelativeLayout)创建自己的实现,并使用它们代替原始布局

    新布局将扩展原始布局,但会覆盖
    draw()
    函数

    原始的draw函数调用
    dispatchDraw()
    ,该函数调用
    drawChild()
    ——只有这样,您才能访问孩子的
    draw()
    。这意味着每个嵌套中的
    draw()。我们将尝试手动将其最小化为1个函数调用

    这是令人厌恶的部分。您熟悉内联
    函数吗?理论上,我们尝试调用
    dispatchDraw()
    drawChild()
    inline。由于java并不真正支持内联,最好的方法是手动将它们内联(实际上是将代码复制粘贴到一个讨厌的函数中)

    这在哪里变得有点复杂?我们将采用的实现将来自Android源代码。问题是,这些来源可能在Android版本之间略有变化。因此,必须映射这些更改,并在代码中创建一组开关,以便与原始代码中的行为完全相同。