Вопрос по android – Простой TextView.setText вызывает использование ЦП на 40%

25

Запуск моего приложения вызывает ~ 40% загрузки процессора на моем телефоне:

final String position = String.format("%02d:%02d:%02d", time.getHours(), time.getMinutes(),
                time.getSeconds());
getActivity().runOnUiThread(new Runnable() {
    @Override
    public void run() {
         c.mTxtPosition.setText(position);
         ...

КомментируяsetText По методу загрузка ЦП снижается до ожидаемого уровня ~ 4%. Метод вызывается каждую секунду и обновляет ImageViews, CustomViews ... не вызывая такого же превышения нагрузки. Помимо использования ЦП, dalvik постоянно сообщает о сборе мусора из 10-1000 объектов, просто вызываяsetText().

Создайте файл трассировки следующим образом:

Debug.startMethodTracing("setText");
c.mTxtPosition.setText(position);
Debug.stopMethodTracing();

В трассировке перечисляются следующие методы как Top 5 по их соответствующим эксклюзивным CPU%:

ViewParent.invalidateChildInParent(16%) View.requestLayout(11%) ViewGroup.invalidateChild(9%) TextView.setText(7%) toplevel(6%)

У кого-нибудь есть объяснение этому?

Я попробовал это. Даже если я вызываю setText ("hugo"), проблема остается. phlebas
No. SetText (..). Это странная вещь. phlebas
Это может быть полезно, но я не об этом. Записывайте больше своего приложения, возможно, используя перспективу DDMS для включения / выключения трассировки метода, а не трассировки некоторого раздела кода. Затем посмотрите, где время тратится не в процентах, а в миллисекундах. Сравнивая это с и безsetText() Вызов должен резко выделить что-то, если ваши значения загрузки процессора являются точными. CommonsWare
Ты действительно имеешь ввиду комментироватьsetText(), или вы имеете в виду комментированиеString.format() вызов?String.format() дорогой CommonsWare
По какой-то причине попробуйте заменитьfinal String position = String.format(...); сfinal String position = "Hi, Mom!"; и посмотри, что получится. Возможно, что некоторые оптимизации компилятора задерживаютformat() звоните, пока не используетеposition переменная в первый раз. Я бы не ожидал этого, но это имеет больше смысла, чем один случайныйsetText() называть быть значительно дороже, чем другие вещи, которые вы делаете. Кроме того, вы можете рассмотреть возможность использования Traceview для получения более точной информации о том, где идет время. CommonsWare

Ваш Ответ

4   ответа
19

я думаю, проблема в том, что каждый раз, когда вы вызываете setText, размер текстового поля может изменяться, что требует релейного выхода на весь экран (дорого).

Я сам еще не пробовал, но если ваше текстовое поле простое и может быть сделано с относительно фиксированным размером, возможно, попытайтесь создать подкласс TextView и создать представление, которое не изменяет свой размер в setText, а просто рисует что угодно может в существующую область? Это сэкономило бы много времени.

Возможно, уже есть флаг setText, который может сделать это, но я не знаю об этом, хотя я не искал внимательно.

Спасибо, действительно, была проблема с моими файлами макетов. Первоначально TextView находился в макете <include />. Я просто слил его в мастер-макет и процессор% вернулся к нормальному состоянию. Таким образом, мы можем сузить это до, может быть, есть специальный атрибут / стратегия включения, которому нужно следовать, чтобы избежать этого. phlebas
@ Тим Ты сделал мой день, брат. Настоятельно рекомендуется иметь фиксированный размер, особенно когда вы используете вид списка. Ранее я использовал "wrap_content", а просмотр списка настолько запаздывает. Как только я изменяю макет на фиксированные значения dp, скорость становится намного быстрее. Yasitha Chinthaka
Подтвердил наверняка - мы только что потратили 3 часа на отладку, и когда мы убрали вызовы setText (), выполнение было заметно другим. Когда мы сделали так, чтобы текстовые представления охватывали всю ширину, мы могли затем вернуть вызовы setText () назад. Quintin Balsdon
2

которое вызывает много обновлений. Решением было изменение TextView layout_width & layout_height на фиксированный размер.

Я столкнулся с той же проблемой, и установкаlayout_width а такжеlayout_height до фиксированного размера действительно сделалsetText() Звони намного быстрее. Благодарность VinceFior
Кроме того, до того как я сделал это изменение, я смог немного улучшить производительность, просто позвонивsetText() если текущий текст (найден черезgetText()) отличался от моего нового текста тем, что он стои VinceFior
1

try с использованием обработчика, который обновляет текстовое представление каждые 0,5 секунды вместо потока, который это делает. сделайте работоспособный конечный постоянный объект вместо создания нового каждую секунду. проверить, что время изменилось (newTimeInMs-LastPublishedTimeInMs> = 1000), прежде чем сообщить текстовому представлению, что оно само обновляется.instead of String.format, попробуйте использовать StringBuilder. однако вам не понравится локальное решение, которое предоставляет String.format (например, для арабских цифр).
Благодарность. Хотя CPU UI Thread% составляет 1%. Так что выгода не будет слишком большой. Я рассмотрел некоторые из этих предложений сам. TextView в настоящее время обновляется после широковещательного приема, что обычно происходит примерно через ~ 1 сек. Что касается проверки времени, это зависит от перспективы. Я ожидаю, что время изменится большую часть времени, поэтому я не проверяю сначала и, следовательно, уменьшаю накладные расходы, если время меняется. Если бы я ожидал, что время изменится не так часто, вы были правы. Извлечение интерфейса, конечно, будет более чистым. И форматирование строк ... Ну, как вы заметили, нужно жить с недостатками. phlebas
На самом деле гарантируется, что время изменилось при каждом вызове. phlebas
да, время проверок, это зависит от вашего кода. если вы используете предложенный мною метод, я думаю, что лучше делать проверку, поскольку вам нужно проверять каждые 0,5 секунды (чтобы у вас был низкий шанс пропустить секунду). android developer
btw, не могли бы вы опубликовать проблемный проект? это может быть хорошим упражнением для других людей ... android developer
Это не часы, поэтому, если вещание останавливается, время останавливается. Что вы имеете в виду, опубликовать проект? Включенный код по сути является BroadcastReceiver, который вызывается над фрагментом. phlebas
0

В моем случае это было свойство TextView:

android:ellipsize="marquee"

Удаление его ускорило настройку текста.

Похожие вопросы