2011-12-16 79 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; 
    } 
} 

也可以是一個小更聰明,以支持一個頭。只要添加一個檢查,如果索引是根目錄並膨脹一個不同的視圖。由於標題是唯一不同的標題,因此您仍然可以利用所有其他可重用的行。你甚至可以預先膨脹並存儲標題並重新使用它來徹底消除通貨膨脹。

相關問題