Програма може зробити занадто багато роботи над її основною темою


379

Я новачок у середовищі Android SDK / API. Це перше, що я намагаюся намалювати сюжет / діаграму. Я спробував запустити різні типи зразкових кодів емулятора за допомогою 3 різних безкоштовних бібліотек, на екрані макета нічого не відображається. Logcat повторює таке повідомлення:

 W / Trace (1378): Несподіване значення від nativeGetEnabledTags: 0
 Я / хореограф (1378): Пропустив 55 кадрів! Програма може зробити занадто багато роботи над її основною темою.

Проблема не зберігалася, і діаграма запрацювала, коли я запустив зразок коду, що стосується копії оцінки ліцензованої бібліотеки.


2
Ви малюєте свої діаграми окремою ниткою?
Арекс

Дякую за Ваш коментар, я відредагував це питання, щоб зробити його більш зрозумілим. Діяльність під час запуску показує, що я виконую діяльність, яка не має дизайну її макет => показує білий екран.
user2038135

1
@Areks Ні, я не використовую окрему нитку.
користувач2038135

1
Я думаю, що вам слід, зовсім не рекомендується виконувати довгі операції над основним потоком, тому що це заморожує всю програму, ви можете прочитати, як тут використовувати теми: stackoverflow.com/questions/3391272/… Ігноруйте код, який потрібно зробити HTTP-запит "і просто виконувати там потенційно довгі операції.
Арекс

1
Чому ви не намагаєтеся шукати, ви знайдете інформацію про хореографа. Я рекомендую вам прочитати цю відповідь: stackoverflow.com/questions/11266535/…
Габріель Естебан

Відповіді:


479

взято з: інтерфейсу Android: виправлення пропущених кадрів

Кожен, хто починає розробляти додаток для Android, бачить це повідомлення на logcat «Хореограф (abc): Пропущено xx кадри! Програма може робити надто багато роботи над її основною темою. " Отже, що це насправді означає, навіщо вас турбувати і як це вирішити.

Це означає, що ваш код займає багато часу, а кадри пропускаються через нього, можливо, через важку обробку, яку ви робите в основі вашої програми або доступу до БД, або будь-яку іншу річ, яка спричиняє потік зупиніться на деякий час.

Ось більш детальне пояснення:

Хореограф дозволяє програмам підключитися до vsync і належним чином виділити час для покращення продуктивності.

Android-анімація для внутрішнього використання використовує «Хореограф» з тією ж метою: належним чином анімувати анімацію та, можливо, підвищити продуктивність.

Оскільки хореограф розповідає про всі події vsync, я можу сказати, чи не проходить один із Runnables, який пройшов повз Choreographer.post * apis, за один кадр, через що кадри можуть бути пропущені.

На мій погляд, хореограф може виявити лише пропуск кадру. Це не може сказати, чому це відбувається.

Повідомлення "Програма може надто багато працювати над головною темою". може ввести в оману.

джерело: Значення повідомлень хореографа в Logcat

Чому ви повинні турбуватися

Коли це повідомлення спливає на емуляторі Android, а кількість пропущених кадрів є досить малою (<100), тоді ви можете взяти на себе безпечну ставку того, що емулятор повільний - що відбувається майже весь час. Але якщо кількість кадрів пропущена і велика і порядку 300+, то з вашим кодом можуть виникнути серйозні проблеми. Пристрої Android оснащені величезним набором апаратних засобів на відміну від пристроїв ios та Windows. Оперативна пам’ять і процесор різняться, і якщо ви хочете розумної продуктивності та користувальницької роботи на всіх пристроях, вам потрібно це виправити. Коли кадри пропускаються, користувальницький інтерфейс працює повільно і мляво, що не є бажаним досвідом користувача.

Як це виправити

Для виправлення цього потрібно ідентифікувати вузли, де існує або, можливо, може тривати тривала обробка. Найкращий спосіб - це зробити всю обробку незалежно від того, наскільки маленька чи велика в потоці, відокремленій від основної нитки інтерфейсу користувача. Нехай це буде доступ до даних у базі даних SQLite або виконання жорсткої математики або просто сортування масиву - зробіть це в іншому потоці

Тепер тут є улов. Ви створите нову тему для виконання цих операцій, і коли ви запустите свою програму, вона вийде з ладу, кажучи: "Тільки оригінальна нитка, яка створила ієрархію перегляду, може торкнутися її поглядів". Вам потрібно знати цей факт, що інтерфейс користувача в android можна змінювати лише основним потоком або потоком інтерфейсу користувача. Будь-який інший потік, який намагається це зробити, виходить з ладу і виходить з ладу з цією помилкою. Що вам потрібно зробити, це створити новий Runnable всередині runOnUiThread, а всередині цього запуску ви повинні виконати всі операції, що стосуються інтерфейсу користувача. Знайдіть приклад тут .

Отже, у нас є Thread and Runnable для обробки даних з основної теми, що ще? В android є AsyncTask, який дозволяє робити тривалі процеси в потоці інтерфейсу користувача. Це найкорисніше, коли ваші програми керуються даними або керуються веб-api або використовують складні інтерфейси, такі як побудовані за допомогою Canvas. Сила AsyncTask полягає в тому, що дозволяє робити речі у фоновому режимі, і як тільки ви закінчите обробку, ви можете просто виконати необхідні дії на інтерфейсі користувача, не викликаючи ефекту відставання. Це можливо, тому що AsyncTask походить від потоку інтерфейсу діяльності Activity - всі операції, які ви робите над користувальницьким інтерфейсом через AsyncTask, - це інший потік від основного потоку інтерфейсу, без перешкод у взаємодії з користувачем.

Тож це те, що потрібно знати для створення плавних програм для Android, і наскільки я знаю, кожен новачок отримує це повідомлення на консолі.


41
У мене просто є додаток, у якому, якщо я натискаю кнопку, фонове зображення кнопки змінюється, і кнопку не можна натискати. Як я роблю занадто багато роботи :(
Remian8985

1
@ Remian8985 - Зміна фонового зображення для кнопки (якщо припустити, що ви завантажуєте це зображення) слід виконати в AsyncTask - тобто виконати цю операцію завантаження фону та опублікувати результат у потоці інтерфейсу користувача (подати зображення назад). Дивіться посилання на
BenJaminSila

11
@BenJaminSila змінює фон в AsyncTask? Дійсно?
користувач25

11
@ user25 "припускаючи, що ви завантажуєте це зображення"
forresthopkinsa

"Коли це повідомлення спливає на емуляторі Android, а кількість пропущених кадрів є досить невеликою (<100), то ви можете взяти безпечну ставку на те, що емулятор повільний" Чи це застосовується і сьогодні? Емулятори стають досить швидко, правда?
Робін Дійхоф

243

Як відповіли інші вище, "Пропустив 55 кадрів!" означає, що у вашій заявці є важка обробка.

У моєму випадку у моїй заяві немає важкого процесу. Я двічі і втричі перевіряв все і видаляв ті процеси, які, на мою думку, були трохи важкими.

Я видалив фрагменти, діяльність, бібліотеки, поки не залишився лише скелет. Але все-таки проблема не пішла. Я вирішив перевірити ресурси і виявив, що деякі значки та фон, які я використовую, досить великі, тому що забув перевірити розмір цих ресурсів.

Отже, я пропоную, якщо жоден з наведених відповідей не допоможе, ви можете також перевірити розмір файлів ресурсів.


1
Працював і для мене. У мене був додаток, який робив дуже мало роботи, але був повільним і млявим. Я продовжував отримувати пропущені журнали кадрів. Після того, як я видалив тло своєї діяльності, все було добре. Дякую!
akrabi

Чудова відповідь, я вважаю, що це була саме моя проблема. Я спробував купу інших (досить залучених) рішень, і додаток було так само повільним. Я вийняв усі веб-сервіси і намагався оптимізувати код до кінця. Не працювало, тоді я це бачив. Щойно я видалив фонове зображення (найбільше у мене зображення), програма працює приблизно так само швидко, як ви можете натискати речі, навіть зі старим "повільним" кодом.
М Барбоса

ти мене вразив!
Ніколя Мастромаріно

:) Ви абсолютний геній.
Метін Ільхан

@batsheva не обов’язково бути 1 Кб. Це залежить від ваших потреб, скажімо, вам потрібні чіткіші зображення, ви можете використовувати більш високу роздільну здатність, але переконайтеся, що ви розділилися на різні розміри в різні папки ресурсів.
Сіту

61

У мене теж була така ж проблема.
Шахта була випадком, коли я використовував фонове зображення, яке було на малюнках. Це конкретне зображення було приблизно 130 кБ і використовувалось під час екрану заставки та домашньої сторінки в моєму додатку для Android.

Рішення - я просто перемістив це зображення в папку drawables-xxx з малюнкових матеріалів і міг звільнити багато пам'яті, зайнятої у фоновому режимі, і пропущені кадри більше не пропускалися.

Оновлення Використовуйте папку драйвових ресурсів 'nodp' для зберігання фонових файлів, що витягуються.
Чи матиме переважну папку для малювання густину чи nodpi перевагу?


7
Я перемістив своє велике фонове зображення з малюваного на mimap-xxxhdpi, і це зробило трюк!
bgplaya

Ви дуже допомогли. Дякую
Н.Дроїд

2
Це рішення робить трюк. Я використовую папку drawable-xxxhdpiзамість drawableтого, що різко зменшує використану пам'ять (~ 70 відсотків менше). Також добре знати, що екрани однакового розміру залежать від розміру DPI. Співвідношення в пікселях між ними ldpi = 1:0.75, mdpi = 1:1, hdpi = 1:1.5, xhdpi = 1:2, xxhdpi = 1:3, xxxhdpi = 1:4. Використовуючи drawable-xxxhdpiпапку, ви дозволяєте зменшити масштаб зображень на екрані свого пристрою, що зменшує обсяг пам'яті та споживання процесора.
Тімо Бах

2
Переміщення зображень drawableдо, щоб drawable-nodpiпрограма не отримувала Out of Memory Error.
Шрути

О боже ... дякую! У мене було зображення в папці, що малюється, і це зробило моє додаток повільним, як пекло (хоча зображення було всього 100 кбіт !!!). Після створення файлів Dravable-xxx (я використовував Android Drawable Importer) моя програма проклята швидко. Дуже дякую!
помилка1337

20

Ще одна поширена причина затримок потоку інтерфейсу - доступ до SharedPreferences. Коли ви PreferenceManager.getSharedPreferencesвперше викликаєте a та інші подібні методи, пов'язаний .xml файл негайно завантажується та розбирається в одному потоці .

Одним із хороших способів боротьби з цією проблемою є запуск першого завантаження SharedPreference з фонового потоку, розпочатого якомога раніше (наприклад, з onCreateвашого класу Application). Таким чином об'єкт уподобань може бути вже побудований до моменту, коли ви хочете його використовувати.

На жаль, іноді читання файлів уподобань є необхідним на ранніх етапах запуску (наприклад, у початковій діяльності або навіть у самій програмі). У таких випадках все-таки можливо уникнути зупинки інтерфейсу користувача за допомогою MessageQueue.IdleHandler. Виконайте все, що вам потрібно виконати в основному потоці, а потім встановіть IdleHandler для виконання коду, коли ваша активність буде повністю намальована. У цьому Runnable ви повинні мати доступ до SharedPreferences, не затримуючи занадто багато операцій з малюванням і не роблячи хореографа нещасним.


1
У цьому випадку вам слід віддати перевагу методу застосовувати () замість commit (). метод apply () не може блокувати інтерфейс користувача. Ви можете подивитися тут developer.android.com/training/data-storage/shared-preferences
Emre Gürses

16

Спробуйте скористатись такими стратегіями, щоб покращити ефективність програми:

  • Використовуйте програмування з декількома нитками, якщо можливо. Переваги від продуктивності величезні, навіть якщо ваш смартфон має одне ядро ​​(потоки можуть працювати в різних ядрах, якщо процесор має два і більше). Корисно, щоб логіка вашої програми була відокремлена від інтерфейсу користувача. Використовуйте потоки Java, AsyncTask або IntentService. Перевірте це .
  • Прочитайте та дотримуйтесь порад щодо різної продуктивності веб-сайту для розробки Android. Перевірте тут .

3
перше посилання вимагає, щоб ви "... мали підтверджений обліковий запис ...", щоб отримати доступ до нього.
хорн

9

У мене була така ж проблема. Емулятор Android відмінно працював на Android <6.0. Коли я використовував емулятор Nexus 5 (Android 6.0), програма дуже повільно працювала з I/Choreographer: Skipped framesжурналами.

Отже, я вирішив цю проблему, змінивши hardwareAcceleratedпараметр файлу Manifest на trueтакий:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapplication">

    <application android:hardwareAccelerated="true">
        ...
    </application>
</manifest>

8

Я не фахівець, але мені надійшло це повідомлення про налагодження, коли я хотів надсилати дані з моєї програми для Android на веб-сервер. Хоча я використовував клас AsyncTask і здійснював передачу даних у фоновому режимі, для повернення результатів даних із сервера я використав метод get () класу AsyncTask, який робить інтерфейс синхронним, що означає, що ваш інтерфейс буде чекати занадто довго. Тому моя порада - змусити ваш додаток виконувати всі завдання, орієнтовані на мережу, окремо.


6

Оптимізуйте свої зображення ... Не використовуйте зображення розміром більше 100 КБ ... Завантаження зображень займає занадто багато процесора, і ваша програма зависає.


4
Зменшіть розмір зображення або за допомогою Java-коду, або використовуйте Photoshop для обрізання зображень. Також стискайте зображення за допомогою компресора.io
HarshitG

5

У мене була така ж проблема. У моєму випадку у мене було 2 вкладених відносних макета. Відносна схема завжди повинна робити два проходи вимірювання. Якщо ви вкладаєте RelativeLayouts, ви отримуєте експоненціальний алгоритм вимірювання.


4

зазвичай це відбувається, коли ви виконуєте величезні процеси в основній потоці. нормально пропускати кадри менше 200. Але якщо у вас більше 200 пропущених кадрів, це може сповільнити використання потоку інтерфейсу програми. що ви можете зробити, це зробити ці процеси в новому потоці під назвою робочий потік, і після цього, коли ви хочете отримати доступ і зробити що-небудь за допомогою потоку інтерфейсу (наприклад, зробити щось із переглядами, findView тощо), ви можете використовувати обробник або runOnUiThread (Мені це більше подобається), щоб відобразити результати обробки. це абсолютно вирішує проблему. використання робочих ниток дуже корисно або навіть їх потрібно використовувати, якщо мова йде про ці випадки.


1

У мене була така ж проблема. Коли я запустив код на іншому комп’ютері, він працював чудово. Однак на моєму екрані було відображено "Програма може надто багато працювати над головною темою".

Я вирішив свою проблему, перезавантаживши студію Android [Файл -> Недійсні кеші / Перезавантажте -> натисніть "Недійсний та перезавантажте"].


Я не знаю, чому ваше рішення спрацювало. Все одно дякую.
Bhuvanesh BS

1

У моєму випадку це було тому, що я випадково встановив точку перелому на методі. Як тільки я його очистив, повідомлення пішло і продуктивність значно покращилась.


0

У моїй програмі була така ж проблема. Але це було не що інше, як показ списку карток та тексту на ньому. У фоновому режимі нічого не працює. Але потім після деякого розслідування з'ясувалося, що набір зображень для фону картки спричиняє це, хоча воно було невеликим (350 кбіт). Потім я перетворив зображення на 9патч зображень за допомогою http://romannurik.github.io/AndroidAssetStudio/index.html .
Це працювало для мене.


0

Після багато досліджень і розробок з цього питання я отримав рішення,

У моєму випадку я використовую Сервіс, який працюватиме кожні 2 секунди, і з runonUIThread, мені було цікаво, що проблема там є, але зовсім не така. Наступне питання, яке я знайшов, - це те, що я використовую великі Image в програмі May, і це проблема.

Я видалив зображення і встановив нові зображення.

Висновок: - Подивіться у свій код, чи є сирий файл, який ви використовуєте, великого розміру.


0

Спочатку прочитайте попередження. Це говорить про більше навантаження на основну нитку. Отже, ви повинні просто запустити функції з більшою роботою в потоці.


-1

У мене виникла ця проблема під час розробки програми, яка використовує багато мальованих png-файлів у макеті сітки. Я також намагався оптимізувати свій код наскільки це можливо .. але це не вийшло для мене .. Тоді я спробував зменшити розмір цих PNG .. і здогадуюсь, що його працює абсолютно добре .. Тож моя пропозиція - зменшити розмір залучених ресурсів, якщо такі є ..

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.