8

我在主 UI 线程(相关问题)中遇到 StackOverflowErrors 问题。我的应用面向 Android 2.3+。在 Android 4 上一切都很好,但是在绘制视图布局时我在 2.3.3 上崩溃了。

显而易见的答案是优化我的视图布局并减少嵌套视图的数量。这是一个问题,因为大量视图是由于我使用了标签的支持库和片段 - 这是推荐的方法。我不想仅仅因为旧版本的操作系统有一个小堆栈就改变我的设计并丢弃片段。

我正在寻找增加 UI 线程堆栈大小的方法。我已经看到了这是不可能的答案,并且我知道清单中没有简单的设置可以做到这一点。但是,我仍然不满意没有手动解决方法。

到目前为止我最好的主意:

创建一个具有更大堆栈的新工作线程(Thread 类)。可以增加工作线程的堆栈大小。然后,以某种方式将此线程转换为新的 UI 线程。如何?

  • 浏览android.app.Activity .attach(..) 的Android 源代码,我看到一个活动将自己附加到一个UI 线程。也许有一些方法可以替换它附加的线程并将其更改为我的“新”UI线程

  • 深入了解android.app.ActivityThread .startActivityNow(..),也许我可以手动启动我的活动。创建活动后,它会自动将自己附加到创建它的线程上。也许如果我从我的新 UI 线程运行它,它会起作用。

  • 如果我创建一个新的 UI 线程,我将不得不为它手动创建 Looper。我了解需要从android.app.ActivityThread .main(..)创建什么

其他想法:

  • 手动捕获 StackOverflowError 并在它发生时异步移动调用,以便它们具有更小的堆栈。我在这里看到了这个好主意,但我无法让它发挥作用。

  • NDK 线程(通过 JNI)有很大的堆栈。我考虑过使用它们来谋取利益,但我认为没有办法做到这一点。所有通过 JNI 的调用都是在它们自己的线程上执行的,所以我看不到如何使用 NDK 线程进行 UI 访问。

所以..

除了说这是一个非常糟糕的主意之外,还有其他建议或提示吗?你能找到做过类似事情的人吗?我不能..

4

2 回答 2

2

可悲的是,CommonsWare 是错误的。仔细检查显示,Android 2.x 上的默认堆栈大小为 12KB,而在 Android 4.x 中已增加到 16KB。这意味着核心团队意识到了小堆栈问题并修复了它。遗憾的是,这些额外的 4KB 是导致崩溃的关键所在。

此外,如果您使用 ABS 等通用库并支持 v4 - 这些库会在您使用片段时将额外的视图添加到您的布局中。由于我们大多数人都依赖这些库,因此说片段可以轻松添加 1 个视图是完全不正确的。如果您使用的是 ABS+support lib,您将为每个片段支付 3 次查看。您将从至少 5 个视图开始(对于 ABS 布局)。

关于手动创建 UI 线程,这可能是可能的,并且可能不需要 root 设备或更改其固件。这些也是可能不正确的粗体陈述。

最后,我决定不使用大堆栈创建自己的 UI 线程。相反,我选择从我的代码中完全放弃使用片段。这在我的布局中总共节省了 5 个视图。片段给你的一切,也可以通过手动添加 ViewGroups 来完成。它只是多一点代码,但没有什么太复杂的。碎片似乎有点没用,如果你没有使用它们的奢侈 - 这是第一个切割的地方。

于 2013-06-06T15:11:23.227 回答
-1

在 Android 4 上一切正常

不,你只是还没有崩溃。我不知道他们增加了 Android 4.x 上的堆栈大小。他们可能使某些小部件更有效率,这使您可以在某些操作中存活更长时间。

这是一个问题,因为大量视图是由于我使用了标签的支持库和片段 - 这是推荐的方法

欢迎您在标签中使用普通Views标签,无论这些标签来自ViewPager(和合适的指示器)、操作栏,甚至是古老的TabHost. 片段不是必需的。

我正在寻找增加 UI 线程堆栈大小的方法

这是不可能的,除非修改 Android 框架并在枪口下迫使约 8 亿 Android 设备用户根植他们的手机并更换他们的框架。即使有可能,除非您能够在数百台设备上进行测试,否则您将不知道您的 hack 是否稳定。

无论如何,在 15 岁时仍然太过分了.. 尤其是当没有人能准确地知道边缘在哪里时

如果我没记错的话,“边缘”是 8KB 的堆栈空间。有才华的程序员意识到,您无法根据层次结构中嵌套视图的数量精确地表达“边缘”,因为堆栈消耗会根据正在执行的操作和操作系统级别而有所不同。

我见过很多人遇到同样的问题

“这么多”的价值相当低。根据公共支持领域提出的问题,多年来这一直不是一个重大问题。

支持库中的选项卡片段活动本身需要 5 个视图。

由于 Android 中没有任何名称为“选项卡片段活动”,因此我们无法为您提供太多帮助,只能建议使用其他选项卡来源。例如,ViewPagerwith TabPagerIndicator(来自ViewPagerIndicator)应该沿着关键路径围绕两个嵌套级别。

那么每个片段至少有 4 个。

有才华的程序员意识到片段甚至不需要视图,因此片段的最小视图数是 0。有才华的程序员还意识到,确实有 UI 的片段至少需要 1 个视图,而不是 4 个,因为你可以返回任何View你想要的onCreateView()——在语义上没有任何东西onCreateView()需要 4。

例如,此示例项目使用ViewPagerwithTabPagerIndicator和 Fragments 作为选项卡。从根到关键路径叶,整个结构有 7 个层次。

在我的个人层次结构中拥有 10 个视图并不奇怪

是的,是的,一旦你添加了所有活动固有的 3 个级别,因为 13 个级别肯定开始让我感到紧张。在我引用的示例中ViewPager,它的选项卡和片段在此之上添加了 4 个级别。如果您说要在选项卡中具有 10 级层次结构,我怀疑是否存在足够苗条的选项卡解决方案,尽管操作栏选项卡是一种可能性。

因此,您的解决方案是:

  • 简化每个选项卡的 10 级层次结构
  • 如果仅此一项还不够,请选择更纤薄的选项卡实现
于 2013-06-04T10:17:19.677 回答