将多个视图添加到 LinearLayout 的最快方法是什么?
我有一个已包含多个元素的 LinearLayout 视图。我想以编程方式向其添加更多视图。因为它位于 ScrollView 内部,所以所有内容都会滚动。
所以我要做的就是浏览我的列表,并向其中添加自定义视图的新实例。该自定义视图扩展了 XML 布局并添加了一些方法。
这种方法效果很好。问题是,即使没有任何疯狂的代码,它也非常慢......一个包含 10 个项目的列表需要大约 500 毫秒才能实例化。从用户体验的角度来看,这是难以接受的。
我的问题是,这是正确/最佳的方法吗?尽管“R.layout.my_list_item”非常简单,Android 似乎还是花了很多时间来扩展布局。我想知道是否有一种方法可以重用“膨胀”布局来获取其他视图,有点缓存更复杂的解析?
我尝试过使用 ListView
(以及适配器和包装器)来完成此操作,它似乎要快得多。问题是我不能使用简单的 ListView
;我的布局比简单的列表更复杂(LinearLayout
本身包含其他自定义图标,并且在被 ScrollView
包装之前,它还有另一个具有更多视图的父级)。
但是有没有办法为 LinearLayout 使用适配器呢?这会比尝试自己添加视图更快吗?
任何帮助表示赞赏。我很想让这更快。
代码如下。
主要活动:
// The LinearLayout that will contain everything
lineList = (LinearLayout) findViewById(R.id.lineList);
// Add a lot of items for testing
for (int i = 0; i < 10; i++) {
addListItem("Item number " + i);
}
protected void addListItem(String __title) {
MyListItem li;
li = new MyListItem(this);
li.setTitle(__title);
lineList.addView(li);
}
MyListItem:
public class MyListItem extends RelativeLayout {
protected TextView textTitle;
public MyListItem(Context __context) {
super(__context);
init();
}
public MyListItem(Context __context, AttributeSet __attrs) {
super(__context, __attrs);
init();
}
public MyListItem(Context __context, AttributeSet __attrs, int __attrsdefStyle) {
super(__context, __attrs, __attrsdefStyle);
init();
}
protected void init() {
// Inflate the XML layout
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.my_list_item, this);
// Create references
textTitle = (TextView)findViewById(R.id.textTitle);
}
public void setTitle(String __text) {
textTitle.setText(__text);
}
}
我想要完成的是这个。考虑以下布局:
此布局是一个 FrameLayout
(外框),其中包含一个 ImageView
(灰色)、一个TextView
(内部矩形,位于顶部)和一个LinearLayout
(内部矩形,位于底部)。这个 LinearLayout
矩形是我动态填充一些项目的矩形。
填充后,我希望最终结果如下(其中每个新矩形都是一个新的 MyListItem
实例):
也就是说,所有内容都是可滚动的(例如,背景图像在顶部对齐)。 LinearLayout
本身不可滚动(其他一切都随之而来),因此据我所知,为什么 ListView
不能很好地工作 就我而言。
I have a LinearLayout
view that already contains several elements. I want to add a lot more Views to it, programmatically. And because this is inside a ScrollView
, everything will be scrolled.
So what I do is go through my list, and add new instances of my custom View to it. That custom view inflates a XML layout and adds a few methods.
This approach works well. The problem is that it's super slow, even without any crazy code... a list with 10 items takes around 500ms to instantiate. As an user experience standpoint, this is hard to swallow.
My question is, is this the correct/best approach? Android seems to take a lot of time inflating the layout, even though "R.layout.my_list_item" is super simple. I wonder if there's a way to maybe to reuse "inflated" layouts for additional views, kinda caching the more complex parsing?
I've tried doing this with a ListView
(and adapter and a wrapper) and it seems to be much faster. The problem is that I can't use a simple ListView
; my layout is more complex than a simple list (the LinearLayout
itself contains additional custom icons, and it has another parent with even more Views before it's wrapped by the ScrollView
).
But is there a way to use an adapter for a LinearLayout? Would that be faster than trying to add the views myself?
Any help is appreciated. I'd love to make this faster.
Code follows.
Main Activity:
// The LinearLayout that will contain everything
lineList = (LinearLayout) findViewById(R.id.lineList);
// Add a lot of items for testing
for (int i = 0; i < 10; i++) {
addListItem("Item number " + i);
}
protected void addListItem(String __title) {
MyListItem li;
li = new MyListItem(this);
li.setTitle(__title);
lineList.addView(li);
}
MyListItem:
public class MyListItem extends RelativeLayout {
protected TextView textTitle;
public MyListItem(Context __context) {
super(__context);
init();
}
public MyListItem(Context __context, AttributeSet __attrs) {
super(__context, __attrs);
init();
}
public MyListItem(Context __context, AttributeSet __attrs, int __attrsdefStyle) {
super(__context, __attrs, __attrsdefStyle);
init();
}
protected void init() {
// Inflate the XML layout
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.my_list_item, this);
// Create references
textTitle = (TextView)findViewById(R.id.textTitle);
}
public void setTitle(String __text) {
textTitle.setText(__text);
}
}
What I'm trying to accomplish is this. Consider this layout:
This layout is a FrameLayout
(outer box) containing a ImageView
(in gray), a TextView
(inner rectangle, on top) and a LinearLayout
(inner rectangle, on bottom). This LinearLayout
rectangle is the one I'm dynamically populating with a few items.
After I populate it, I want the final result to be this (where every new rectangle is a new MyListItem
instance):
That is, everything is scrollable (the background image, for example, is aligned on top). The LinearLayout
isn't scrollable by itself (everything else follows) hence why a ListView
, from what I know, wouldn't work very well
in my case.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
3 个选项:
将所有内容替换为 ListView,并将其他父级和自定义图标作为 ListView 的标题视图。 ListView 速度更快,因为它只在需要时创建视图。
以编程方式创建 my_list_item 的内容而不是膨胀,可能会更快
使用 ViewStubs 可能允许您按需加载视图。
也许它不是加载视图而是数据?在这种情况下,在后台线程中准备数据。
3 Options:
Replace everything with a ListView, with the other parent and custom icons as a header view for the ListView. ListView is faster, because it only creates Views as it needs them.
Programatically create the contents of my_list_item instead of inflating, might be quicker
Use of ViewStubs may allow you to load views on-demand.
Maybe it isn't loading the views but the data? in which case prepare the data in a background thread.
ListView
是最佳选择。你说你的布局太复杂了。但作为一个孩子,膨胀一个复杂的布局是完全可以的。例如,一个包含文本和图标的布局:
可以在您的适配器中膨胀,如下所示:
您也可以更聪明一点来支持标题。只需添加检查索引是否为根并膨胀不同的视图。由于标题是唯一不同的行,因此您仍然可以利用所有其他可重用的行。您甚至可以预充气并存储标头并重复使用它以完全消除充气。
A
ListView
is the way to go.You say that your layout is too complex. But it is completely okay to inflate a complex layout as a child. For example a layout that has text and then an icon:
Could be inflated in your adapter as so:
You can also be a little more clever in order to support a header. Just add a check if the index is the root and inflate a different view. Since the header is the only one that is different you will still take advantage of all the other rows being reusable. You can even pre-inflate and store the header and reuse it to completely get rid of inflation.
只需使用 ListView 即可!
它是最容易设置和维护的。您可以为列表行定义 XML 布局,并为保存整个列表的视图定义 XML 布局。 ListAdapter 会为您完成剩下的工作。
只需创建一个:
...并循环遍历您的数据,即可将任意数量的项目添加到地图中。然后将此映射设置为您的 ListAdapter。无论是 10 个项目还是 100 个项目,ListAdapter 都会创建一个包含那么多项目的列表。
例子:
Just use a ListView!
It's the easiest to set up and easiest to maintain. You define an XML layout for the List-Row, and an XML layout for the View which holds the entire List. The ListAdapter does the rest for you.
Just create a:
...and loop through your data to add as many items as you like to the Map. Then set this map to your ListAdapter. Whether 10 items or 100 items the ListAdapter will create a List with that many items.
Example: