向LinearLayout添加多个视图的最快方法是什么?

时间:2011-12-16 21:59:19

标签: android layout view android-linearlayout inflate

我有一个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);
    }
}

我想要完成的是这个。考虑这种布局:

Basic layout

此布局为FrameLayout(外框),其中包含ImageView(灰色),TextView(内部矩形,顶部)和LinearLayout(内部)矩形,在底部)。这个LinearLayout矩形是我用几个项目动态填充的矩形。

填充之后,我希望最终结果为(每个新矩形都是新的MyListItem实例):

Populated layout

也就是说,一切都是可滚动的(例如,背景图像在顶部对齐)。 LinearLayout本身不可滚动(其他所有内容都可以跟随),因此根据我所知,ListView为什么不能很好地工作 就我而言。

3 个答案:

答案 0 :(得分:7)

3个选项:

  1. 使用ListView替换所有内容,其他父级和自定义图标作为ListView的标题视图。 ListView更快,因为它只根据需要创建视图。

  2. 以编程方式创建my_list_item的内容而不是膨胀,可能更快

  3. 使用ViewStubs可能允许您按需加载视图。

  4. 也许它没有加载视图而是加载数据?在这种情况下,在后台线程中准备数据。

答案 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);
    }