【发布时间】:2013-03-06 05:59:50
【问题描述】:
我想弄清楚 Android 布局和视图的主要有效性问题。我现在正在做一项研究,但也许有人已经有了答案。
我有一个动态填充视图的RelativeLayout。基本上,应用程序在 XML 中加载论坛线程,然后呈现讨论树,因此每条消息都显示在其自己的视图组中。我决定不使用WebView,因为我想实现一些在自定义视图上比在 HTML 页面上更容易实现的客户端功能。
但是这种方法有一个重大缺陷:它很重。
第一个问题(我已经解决了)是nesting of views。现在这不是问题,我的布局几乎是平的,因此最大深度为 10-12(从最顶部的 PhoneWindow$DecorView 开始计算,实际深度取决于数据)。
现在我已经达到了下一个限制,该限制以某种方式与视图的资源消耗相关(或由其引起)。加载数据后,应用程序挂起一段时间以构建布局(创建视图并用数据填充它们),挂起时间似乎与数据大小呈线性增长;如果数据足够大,视图将永远不会出现(最终系统建议关闭应用程序,因为它没有响应)。
现在的问题:
内存消耗是否很大程度上取决于视图类?换句话说,
Button和TextView或ImageView之间有什么重大区别吗?我可以将点击处理程序附加到任何视图,因此它们在使用上不会有太大差异。背景图片会影响性能吗?如果在
N视图中设置相同的图像,它会使布局N倍重吗? (我知道这个问题可能看起来很傻,但无论如何。)九块图像是否比普通图像重得多?更好的是:创建
N视图,每个视图都有一些背景图像,或者创建一个宽N倍且具有重复背景的视图?给定一些布局,首先应该优化什么:视图总数、嵌套级别或其他?
最有趣的。这是否可以测量或至少估计活动及其视图消耗的资源?如果我做出一些改变,我怎么能看到我走的是正确的道路?
更新
感谢 User117,我上面提出的一些问题现在得到了解答。我使用了 Hierarchy Viewer 并优化了布局:与之前相比,现在的总视图数量减少了近两倍,嵌套也减少了。
但是应用程序仍然挂在一个大型论坛线程上。
更新 2
我已将调试器连接到我的设备,发现应用程序内存不足。
但对我来说非常意外的是错误发生在我填充布局之后。顺序如下:
- 我的所有观点都已添加。在添加它们时,我可以看到稍微慢了一点。
- 几秒钟内几乎没有任何反应。在此期间,日志中生成了一些信息消息,它们是相同的:
[global] Loaded time zone names for en_US in XXXXms,唯一的区别是毫秒数。 - 产生内存不足错误消息:
[dalvikvm-heap] Out of memory on a N-byte allocation(实际大小不同)。冗长的错误报告开始。
这是什么意思?看起来渲染有自己的需求,可能相当大。
更新 3
我终于找到了核心问题。这是我的应用程序的屏幕截图,请参阅图片下方的说明。
每条消息都包含一个显示或隐藏回复的圆形按钮和按钮右侧的红色内容框。这非常简单,只需要 6 个视图,包括布局。
问题在于这些连接线的缩进显示了哪些消息与哪个消息相关。
在我当前的实现中,缩进由小的ImageView 构成,每个都包含一个正方形图像,显示空白区域、垂直线、T 形连接器或L 形角。所有这些视图在包含整个讨论树的大型 RelativeLayout 中相互对齐。
这适用于小型和中型树(最多数百条消息),但是当我尝试加载大型树(2K+ 条消息)时,我得到了上面更新 2 中解释的结果。
显然,我在这里有两个问题。我生成了大量消耗内存的视图,这些视图是 ImageView 的,它们需要更多的内存进行渲染,因为它们渲染位图并因此创建图形缓存(根据 cmets 中的 User117 给出的解释)。
我尝试禁用将图像加载到缩进视图中,但没有效果。似乎添加大量视图足以吃掉所有可用内存。
我的另一个想法是为每条消息创建一个包含所有管道和角的缩进图像,这样每条消息都将有唯一的缩进视图,而不是 10 或 20 个。但这更加消耗:我已经出去了在填充布局中间的内存。 (我将图像缓存在地图中,因此不会创建具有相同图像序列的两个位图,这没有帮助。)
所以我得出的结论是我陷入了死胡同。有没有可能一次画出所有这些线?
【问题讨论】:
标签: android performance android-layout android-view