2011-12-19 4 views
4

Я работаю над Android-приложением, которое сталкивается с проблемами производительности. Моя цель - получить строки из AsyncTask и отобразить их в TextView. TextView изначально пуст, и каждый раз, когда другой процесс отправляет строку, она объединяет его с текущим содержимым текстового поля. Я сейчас использую StringBuilder для хранения основной строки и каждый раз, когда я получаю новую строку, я добавить его к StringBuilder и вызватьКак эффективно обновлять текстовые объявления Android?

myTextView.setText(myStringBuilder.toString()) 

Проблема в том, что фоновый процесс может отправить до 100 строк в секунду , и мой метод недостаточно эффективен.

Перерисовка весь TextView каждый раз, очевидно, плохая идея (временная сложность O (N²)), но я не вижу другого решения ...

ли вы знаете альтернативы TextView, которые могли бы сделать это конкатенации в O (N)?

ответ

2

Наконец-то я нашел ответ с помощью hasxz и Greyson здесь, а также код here. По мере того как струны поступали в пакеты, я решил обновить интерфейс каждые 100 мс. Для записи, вот что мой код выглядит следующим образом:

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) ставит себе запрос обновления 100 мс позже. lock используется совместно с процессом, который отправляет новые строки и устанавливает output_upToDate в false.

2

Пока существует строка новой строки между строками, вы можете использовать ListView для добавления строк и удерживать сами строки в ArrayList или LinkedList, к которым вы добавляете, когда AsyncTask принимает строки.

Возможно, вы также можете считать недействительным 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()); 
} 

ПРИМЕЧАНИЕ: Код выше только для иллюстрации, так что вы, возможно, придется изменить его в соответствии с вашими потребностями.

Смежные вопросы