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.
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.