Несколько TextViews обновляются очень медленно
У меня есть Служба, которая отправляет Intent на мою активность каждые 0,1 секунды. Я использую его для обновления пользовательской реализации хронометра. Здесь все идет правильно. Проблема возникает, когда я хочу обновить 14 TextView, которые у меня есть в TableView внутри фрагмента в моей работе. Здесь приложение очень медленно.
Метод в моей деятельности, где он получает намерение от Сервиса:
private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
long milis = intent.getLongExtra("milis",0);
if( mFragment != null)
mFragment.Update(milis);
}
};
Код внутри Фрагмента, где я обновляю TextViews:
public void actualizarTiempoJuego(long milis){
// Se recuperan los tiempos acumulados y se aumenta la cantidad pasada como parámetro
for(int i=0;i<7;++i) {
long mCurrentMilis1 = mVectorMilis1.get(i);
long mCurrentMilis2 = mVectorMilis2.get(i);
TextView1 t1 = mListaTitularLayoutLocal.get(i);
TextView1 t2 = mListaTitularLayoutVisitante.get(i);
t1.setText(String.value(milis + mCurrentMilis1));
t2.setText(String.value(milis + mCurrentMilis2));
}
}
Я делаю что-то не так, или просто я пытаюсь сделать что-то очень сложное с точки зрения эффективности?
Ответы
Ответ 1
@Sherif поднимает хорошую точку зрения о скрытых значениях альфа, которые сильно убавляют ваше приложение.
В зависимости от вашей платформы вы также можете проверить
<application android:hardwareAccelerated="true"... />
Еще одна вещь, которую вы можете изучить, которая может помочь в производительности, - это не отключение всех этих намерений. Как только вы начнете стрелять, вы получаете систему и в зависимости от того, как они решаются, может потребоваться некоторое дополнительное время.
Для этой проблемы мне нравится использовать Handlers. Они более легкие, чем намерения.
Вы также можете посмотреть AsyncTask. Это в основном как поток, но также дает перехваты, которые запускаются в потоке пользовательского интерфейса, поэтому вы можете выполнять как фоновое действие, так и обновлять пользовательский интерфейс без необходимости отправлять runnables.
EDIT: Наконец, вы всегда можете запускать свои макеты с помощью layoutopt. Мне лично рассказал сам Ромен Гай, что если ваш рисунок слишком медленный, вам нужно меньше рисовать. Просто просмотрите скриншот (из дерева с минимальным представлением, но хорошо в пределах max) из инструмента профилирования. Вы можете видеть, сколько занимает рисование ресурсов. Очень важно держать это как можно более тонкими, если вы хотите, чтобы ваше приложение было отзывчивым.
![Profiling View Drawing Resource Consumption]()
EDIT: он больше не называется layoutopt, он называется lint. Проверьте свой файл ~/android-sdk/tools/
Ответ 2
Я когда-то сталкивался с ситуацией, когда фрагмент был очень медленным.
Я просто предсказываю, что ваш фрагмент имеет какую-то альфу и нарисован на "тяжелой" активности.
Вывод: каждый раз, когда вы устанавливаете текст текстового представления, вся ваша иерархия представлений недействительна.
Кажется, что фрагменты имеют этот недостаток. В любом случае, используйте фрагмент вместо фрагмента и проверьте, остается ли он "медленным".
ДОПОЛНЕНИЕ: текстовое представление wrap_content приведет к значительно большей задержке после setText
, чем текстовое представление fill_parent.
Ответ 3
Вероятно, вы столкнулись с замедлением из-за управления компоновкой с помощью TableLayout и TextView. Каждый раз, когда вы обновляете текст в одном из них, должно выполняться большое количество измерений, чтобы помещать символы в нужное место на экране. Вы действительно должны просто профилировать приложение самостоятельно, используя Traceview, чтобы узнать. Дополнительная информация: http://developer.android.com/tools/debugging/debugging-tracing.html
У меня была та же самая проблема, которую вы видите с тем же типом макета (Fragment > TableLayout > Multiple TextViews). Один из способов проверить, является ли ваша установка TableLayout/TextView виной, - это просто заменить все это одним TextView. Это, вероятно, будет работать очень хорошо. Затем добавьте 14 просмотров в FrameLayout или RelativeLayout. Даже если все они перекрываются, вы все равно должны получать приличную производительность, потому что это сложность измерений в представлении TableLayout, которые действительно приводят к замедлению.
Ответ 4
Как кто-то сказал, что вы можете использовать HardwareAccelerated, но это не отличное решение, вы будете тратить баран и процессор, если вы не сможете решить его по-другому. Решение, вероятно, более безопасно, чтобы уменьшить количество TextView. Попытайтесь уменьшить 14 до 7, и он будет идти в два раза быстрее. Обычно это сложно сделать, но если вы поместите объекты в положение стратегии, пара TextView один над другим может быть вместе, если вы создадите TextView с двумя строками. И не забывайте, что findViewById так дорого, если вы будете использовать объект вида, часто его можно найти один раз и сохранить его ссылку.
Ответ 5
Тесты всегда полезны для определения того, откуда на самом деле происходит медлительность, но я уверен, что предложение Intent, вероятно, намного медленнее, чем обновление 14 TextView. Отправка 10 намерений в секунду - это знак того, что вы делаете это неправильно (TM). Это не то, для чего они предназначены.
Я делаю что-то не так, или просто я пытаюсь сделать что-то очень сложное с точки зрения эффективности?
Обновление 14 TextViews в секунду не является по своей сути сложным; вы должны быть в состоянии легко достичь этого с помощью более подходящего дизайна приложения. ASyncTask или Handler приходят на ум но трудно понять, что лучше, не зная больше о том, что вы пытаетесь сделать.
Ответ 6
-
Вы можете попытаться объявить vars вне цикла:
public void actualizarTiempoJuego(long milis){
// Se recuperan los tiempos acumulados y se
// aumenta la cantidad pasada como parámetro
long mCurrentMilis1;
long mCurrentMilis2;
TextView1 t1;
TextView1 t2;
for(int i=0;i<7;++i) {
mCurrentMilis1 = mVectorMilis1.get(i);
mCurrentMilis2 = mVectorMilis2.get(i);
t1 = mListaTitularLayoutLocal.get(i);
t2 = mListaTitularLayoutVisitante.get(i);
t1.setText(String.value(milis + mCurrentMilis1));
t2.setText(String.value(milis + mCurrentMilis2));
}
}
-
И до setText()
со смешанным типом вы можете попробовать setText("" + milis + mCurrentMilis2);