2011-12-19 52 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()); 
} 

注:上面的代码只是为了说明,所以你可能要改变它,按您的需求。