2011-12-19 55 views
4

我正在研究遇到性能問題的Android應用程序。 我的目標是從AsyncTask接收字符串並將它們顯示在TextView中。 TextView最初是空的,每當其他進程發送一個字符串將其連接到textview的當前內容時。 我目前使用StringBuilder存儲主串,每一次我收到一個新的字符串,我把它添加到StringBuilder並調用如何有效地更新Android textview?

myTextView.setText(myStringBuilder.toString()) 

的問題是,後臺進程可發送高達每秒100個字符串,而我的方法效率不夠高。

重繪整個TextView的每次顯然是一個糟糕的主意(時間複雜度爲O(N²)),但我沒有看到另一種解決方案...

你知道一個替代的TextView可能做這些的O(N)中的連接?

回答

2

我終於在havexz和Greyson的幫助下找到了答案,代碼here。 當字符串爆發時,我選擇每隔100ms更新一次UI。 爲了記錄在案,這裏是我的代碼如下所示:

private static boolean output_upToDate = true; 

/* Handles the refresh */ 
private Handler outputUpdater = new Handler(); 

/* Adjust this value for your purpose */ 
public static final long REFRESH_INTERVAL = 100;  // in milliseconds 

/* This object is used as a lock to avoid data loss in the last refresh */ 
private static final Object lock = new Object(); 


private Runnable outputUpdaterTask = new Runnable() { 

    public void run() { 
     // takes the lock 
     synchronized(lock){ 
      if(!output_upToDate){ 
       // updates the outview 
       outView.setText(new_text); 
       // notifies that the output is up-to-date 
       output_upToDate = true; 
      } 
     } 
     outputUpdater.postDelayed(this, REFRESH_INTERVAL); 
    } 

}; 

,我把這個在我的onCreate()方法:

outputUpdater.post(outputUpdaterTask); 

幾點說明:當我的應用程序調用其onCreate()方法,我outputUpdater處理程序接收一個請求刷新。但是這個任務(outputUpdaterTask)在100ms後提出刷新請求。 lock與發送新字符串並將output_upToDate設置爲false的進程共享。

2

只要字符串之間存在換行符,就可以使用ListView來追加字符串,並將字符串本身保存在AsyncTask接收字符串時添加到的ArrayList或LinkedList中。

您可能會考慮簡單地使TextField失效的次數減少;說每秒10次。這肯定會提高響應能力。像下面的內容可以工作:

static long lastTimeUpdated = 0; 
if(receivedString.size() > 0) 
{ 
    myStringBuilder.append(receivedString); 
} 
if((System.currentTimeMillis() - lastTimeUpdated) > 100) 
{ 
    myTextView.setText(myStringBuilder.getChars(0, myStringBuilder.length()); 
} 

如果串進來爆發 - 比如,你有突發之間的延遲比,說大,第二個 - 然後復位定時器每次更新,將觸發該代碼再次運行以拾取最後一次爆發的尾部。

1

嘗試限制更新。所以不要每秒更新100次,因爲這是生成的速度。保持字符串生成器中的100個字符串,然後每秒更新一次。

代碼想:

StringBuilder completeStr = new StringBuilder(); 
StringBuilder new100Str = new StringBuilder(); 
int counter = 0; 

if(counter < 100) { 
    new100Str.append(newString); 
    counter++; 
} else { 
    counter = 0; 
    completeStr.append(new100Str); 
    new100Str = new StringBuilder(); 
    myTextView.setText(completeStr.toString()); 
} 

注:上面的代碼只是爲了說明,所以你可能要改變它,按您的需求。