Как эффективно обновлять текстовые представления Android? - PullRequest
4 голосов
/ 19 декабря 2011

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

myTextView.setText(myStringBuilder.toString())

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

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

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

Ответы [ 3 ]

2 голосов
/ 24 декабря 2011

Я наконец-то нашел ответ с помощью havexz и Greyson здесь, и некоторый код здесь .Поскольку строки приходили пакетными сигналами, я решил обновлять интерфейс каждые 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() method, my outputUpdater Обработчик получает один запрос на обновление.Но эта задача (outputUpdaterTask) ставит себе запрос на обновление через 100 мс.lock используется совместно с процессом, который отправляет новые строки, и устанавливает для output_upToDate значение false.

2 голосов
/ 19 декабря 2011

Пока есть новая строка между строками, вы можете использовать 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 голос
/ 19 декабря 2011

Попробуйте регулировать обновление. Таким образом, вместо обновления 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());
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...