我有一个LinearLayout
视图已包含多个元素。我想以编程方式添加更多视图。因为它位于ScrollView
内,所以一切都会滚动。
所以我要做的就是浏览我的列表,并将自定义View的新实例添加到其中。该自定义视图会扩展XML布局并添加一些方法。
这种方法效果很好。问题是它的速度非常慢,即使没有任何疯狂的代码......一个包含10个项目的列表需要大约500ms才能实例化。从用户体验的角度来看,这很难被接受。
我的问题是,这是正确/最好的方法吗? Android似乎需要花费大量时间来夸大布局,即使" R.layout.my_list_item"非常简单。我想知道是否有可能重用"膨胀"其他视图的布局,有点缓存更复杂的解析?
我尝试使用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
为什么不能很好地工作
就我而言。
答案 0 :(得分:7)
3个选项:
使用ListView替换所有内容,其他父级和自定义图标作为ListView的标题视图。 ListView更快,因为它只根据需要创建视图。
以编程方式创建my_list_item的内容而不是膨胀,可能更快
使用ViewStubs可能允许您按需加载视图。
也许它没有加载视图而是加载数据?在这种情况下,在后台线程中准备数据。
答案 1 :(得分:2)
可以选择ListView
。
你说你的布局太复杂了。但是,作为一个孩子,将复杂的布局充气是完全可以的。例如,具有文本然后是图标的布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
可以在适配器中充气:
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
LinearLayout root = null;
ImageView editImageView;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
root = (LinearLayout)inflater.inflate(R.layout.item, null);
} else {
root = (LinearLayout)convertView;
}
}
为了支持标题,你也可以更聪明一些。只需添加一个检查索引是否为根,并为另一个视图充气。由于标头是唯一不同的标头,因此您仍然可以利用所有其他可重用的行。您甚至可以预先膨胀并存储标题并重复使用它以完全消除通货膨胀。
答案 2 :(得分:1)
只需使用ListView!
这是最容易设置和最容易维护的。您可以为List-Row定义XML布局,并为View保留整个List的XML布局。 ListAdapter为您完成剩下的工作。
只需创建一个:
List<HashMap<String, String>> services = new ArrayList<HashMap<String, String>>();
...并循环浏览您的数据,以便为地图添加任意数量的项目。然后将此地图设置为ListAdapter。无论是10个项目还是100个项目,ListAdapter都会创建包含那么多项目的List。
示例:
public void updateProductList(String searchTerm) {
createOrOpenDB(this);
Cursor cursor = (searchTerm!=null)? dbAdapter.fetchWhere(TBL_NAME, KEY_NAME+" LIKE '%"+searchTerm+"%'")
: dbAdapter.fetchAll(TBL_NAME);
int rows = cursor.getCount();
if (rows<=0) return;
services.clear(); //clear current list
for (int i=0; i<rows; i++) {
HashMap<String, String> map = new HashMap<String, String>();
cursor.moveToPosition(i);
map.put(KEY_NAME, "" + cursor.getString(cursor.getColumnIndex(KEY_NAME)));
map.put(KEY_DESC, "" + cursor.getString(cursor.getColumnIndex(KEY_DESC)));
map.put(KEY_COST, "" + cursor.getDouble(cursor.getColumnIndex(KEY_COST)));
services.add(map);
}
cursor.close();
closeDB();
ListAdapter adapter = new SimpleAdapter(this, services, R.layout.products_view_row,
new String[] {KEY_NAME, KEY_DESC, KEY_COST},
new int[] {R.id.listViewText1, R.id.listViewText2, R.id.listViewText3});
setListAdapter(adapter);
}