16

我有一个LinearLayout已经包含几个元素的视图。我想以编程方式向它添加更多视图。因为这是在 a 里面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);       
}

我的列表项:

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实例):

填充布局

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

4

3 回答 3

7

3个选项:

  1. 将所有内容替换为 ListView,并将其他父图标和自定义图标作为 ListView 的标题视图。ListView 更快,因为它只在需要时创建视图。

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

  3. 使用ViewStub可以让您按需加载视图。

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

于 2011-12-16T22:20:01.360 回答
2

AListView是要走的路。

你说你的布局太复杂了。但是小时候给复杂的布局充气是完全可以的。例如具有文本和图标的布局:

<?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;
    }
}

为了支持标题,您还可以更聪明一点。只需添加检查索引是否为根并膨胀不同的视图。由于标题是唯一不同的标题,您仍然可以利用所有其他可重复使用的行。您甚至可以预先膨胀并存储标头并重复使用它以完全摆脱通货膨胀。

于 2011-12-16T23:02:33.720 回答
1

只需使用 ListView!

它是最容易设置和最容易维护的。您为 List-Row 定义一个 XML 布局,并为包含整个 List 的 View 定义一个 XML 布局。ListAdapter 会为您完成其余的工作。

只需创建一个:

List<HashMap<String, String>> services = new ArrayList<HashMap<String, String>>();

...并循环访问您的数据以向地图中添加任意数量的项目。然后将此映射设置为您的 ListAdapter。无论是 10 个项目还是 100 个项目,ListAdapter 都会创建一个包含那么多项目的列表。

例子:

    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);
    }
于 2011-12-16T22:42:34.790 回答