2011-12-16 73 views
15

我有一个LinearLayout视图,已经包含几个元素。我想以编程方式为其添加更多视图。因为这是在ScrollView里面,所有的东西都会滚动。将几个视图添加到LinearLayout的最快捷方式是什么?

所以我所做的是通过我的列表,并添加我的自定义视图的新实例。该自定义视图扩大了XML布局并添加了一些方法。

这种方法效果很好。问题是,它超级慢,即使没有任何疯狂的代码...一个包含10个项目的列表大约需要500ms来实例化。作为用户体验的角度来看,这很难让人接受。

我的问题是,这是正确的/最好的办法?尽管“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); 
    } 
} 

我试图做到的是这个。考虑这个布局:

Basic layout

这种布局是一个FrameLayout(外箱)含有ImageView(灰色),一个TextView(内部矩形,在顶部)和LinearLayout(内部矩形,上底)。这个LinearLayout矩形是我动态填充几个项目的矩形。

后,我填充它,我想最后的结果是这样(其中每一个新的矩形是一个新的MyListItem实例):

Populated layout

也就是说,一切都是滚动(背景图像,用于例如,顶部对齐)。 LinearLayout本身不可滚动(其他所有内容),因此我所知道的ListView为什么在我的情况下效果不佳 。

+1

您在该活动中拥有多少个元素,并且您是否有任何定制类继承了UI元素? – 2011-12-16 22:06:03

+0

ListViews非常快,因为它们可以循环使用项目布局。他们夸大填充屏幕所需的项目布局数量。当您向下滚动时,顶部的一个视图会被隐藏,并且会显示底部的一个视图。列表视图从顶部取出旧的不可见视图,并将新数据放在底部。避免昂贵的通货膨胀。总的来说:这里看起来*非常低效,我很确定你想要做什么可以用listview来完成。如果您显示您尝试过的内容并发布您的预期布局草图,我们可以帮助您确定这一点。 – 2011-12-16 22:07:28

+0

保罗:元素不多。也许是4或5.是的,其中一些是自定义类,从基本框架继承。 alextsc:谢谢你的解释。我添加了一个图表,可以更好地解释我的情况,所以我很清楚是否以及如何使用ListView(而不是)。 – zeh 2011-12-16 22:29:29

回答

7

3个选项:

  1. 替换一切与一个ListView,与其它亲和自定义图标作为为ListView报头视图。 ListView速度更快,因为它只根据需要创建视图。

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

  3. 使用ViewStubs可能让你的按需加载的看法。

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

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

也可以是一个小更聪明,以支持一个头。只要添加一个检查,如果索引是根目录并膨胀一个不同的视图。由于标题是唯一不同的标题,因此您仍然可以利用所有其他可重用的行。你甚至可以预先膨胀并存储标题并重新使用它来彻底消除通货膨胀。

相关问题