2013-02-12 63 views
2

我正在嘗試將多個文本視圖添加到已經充滿膨脹的佈局。顯示的信息正在從數據庫中提取,爲數據庫中的每一行創建一個文本視圖。由於數據庫可能非常大,因此我在後臺線程中一次創建一個textview,並將其添加到前景中。從後臺線程添加視圖

這裏是在後臺調用線程來更新前景的功能:

private TextView temp; 
private void addClickableEvent(ReviewHistoryEvent e){ 
    if(e == null){ 
     Log.e(tag,"Attempted to add a null event to review history"); 
     return; 
    } 
    TextView t = new TextView(getBaseContext()); 
    t.setTag(e); 
    t.setText(e.getTime()+" "+e.getEvent()); 
    t.setClickable(true); 
    t.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); 
    t.setTextAppearance(getBaseContext(), R.style.Information_RegularText); 
    t.setGravity(Gravity.CENTER); 
    t.setOnClickListener(this); 

    temp = t; 
    runOnUiThread(new Runnable() { 
     public void run() { 
      LinearLayout display = (LinearLayout) findViewById(R.id.reviewHistory_display); 
      display.addView(temp); 
     } 
    }); 
} 

該功能一旦成功運行,並出現第一個TextView的。但是,當它被第二次調用時,它在display.addView(temp);上失敗。行與以下錯誤:

java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the childs's parent first. 

我不確定爲什麼我的textview已經有一個父母,如果它被認爲是新實例化。此外,我使用臨時文本視圖來解決我的runnable無法引用本地textview t。它是否正確?任何幫助,將不勝感激。

+2

你可能有玩弄這一點。如果你使用'final TextView t'和'addView(t)'而不是使用成員變量?此外,請嘗試刪除所有'。*()'調用,看看它是否仍然失敗。 – Eric 2013-02-12 20:50:31

+0

我同意Eric,嘗試使用最終的'TextView'變量。也嘗試爲每個視圖設置一個唯一的ID('setId(int)')。 – Leandros 2013-02-12 20:56:24

+0

@Eric我會讓你的評論成爲一個答案,無論如何我都會讚揚它。我幾乎肯定這確實是問題。 'Runnable'正在排隊,可能會連續執行幾次,所有對'temp'的引用都是同一個變量,它們指向同一個對象。使用'最終的TextView t'修復了這個問題。符合觀察到的行爲。 – kabuko 2013-02-12 21:28:05

回答

3

而不是使用一個成員變量(可以修改,這是不是本地的,當然)的,使用final TextView代替:

final TextView t = new TextView(getBaseContext()); 
// ... 

temp = t; // Remove this 
runOnUiThread(new Runnable() { 
    public void run() { 
     // ... 
     display.addView(t); 
    } 
});