Uygulama ana iş parçacığında çok fazla iş yapıyor olabilir


379

Android SDK / API ortamında yeniyim. İlk olarak bir arsa / grafik çizmeye çalışıyorum. Emülatör 3 farklı ücretsiz kütüphane kullanarak farklı türde örnek kodları çalıştırmayı denedim, düzen ekranında hiçbir şey gösterilmiyor. Logcat aşağıdaki mesajı tekrarlıyor:

 W / İzleme (1378): nativeGetEnabledTags öğesinden beklenmeyen değer: 0
 I / Koreograf (1378): 55 kare atlandı! Uygulama ana iş parçacığı üzerinde çok fazla iş yapıyor olabilir.

Sorun devam etmedi ve lisanslı bir kitaplığın değerlendirme kopyasıyla ilgili örnek bir kod çalıştırdığımda grafik çalıştı.


2
Grafiklerinizi ayrı bir dizide mi çiziyorsunuz?
Areks

Yorumunuz için teşekkürler, soruyu daha açık hale getirmek için düzenledim. Çalışırken aktivite ben onun düzeni => beyaz bir ekran gösteren tasarımı olmayan bir etkinlik çalıştırıyorum gösteriyor.
user2038135

1
@Areks Hayır, ayrı bir iş parçacığı kullanmıyorum.
user2038135

1
Sanırım, ana iş parçacığı üzerinde uzun işlemler gerçekleştirmek için hiç tavsiye edilmez, çünkü bu tüm uygulamayı dondurur, iş parçacıklarını nasıl kullanacağınızı buradan okuyabilirsiniz: stackoverflow.com/questions/3391272/… "kodu yoksay HTTP isteği "ni seçin ve orada potansiyel olarak uzun işlemlerinizi gerçekleştirin.
Areks

1
Neden aramayı denemiyorsunuz, koreograf hakkında bilgi bulacaksınız. Bu yanıtı okumanızı tavsiye ederim: stackoverflow.com/questions/11266535/…
Gabriel Esteban

Yanıtlar:


479

Alınan: Android UI: Atlanan çerçeveleri düzeltme

Android uygulaması geliştirmeye başlayan herkes bu mesajı logcat'te görüyor “Koreograf (abc): Atlanan xx çerçeveleri! Uygulama ana iş parçacığında çok fazla iş yapıyor olabilir. ” Peki bu ne anlama geliyor, neden endişelenmelisiniz ve nasıl çözülmeli.

Bunun anlamı, kodunuzun işlenmesi uzun sürdüğü ve bu nedenle çerçevelerin atlandığı, belki de uygulamanızın veya DB erişiminizin veya yaptığınız iş parçacığının kalbine yaptığınız bazı ağır işlemler nedeniyle olabilir. bir süre dur.

İşte daha ayrıntılı bir açıklama:

Koreograf, uygulamaların kendilerini vsync'e bağlamasına ve performansı artırmak için işleri düzgün bir şekilde zamanlamasına olanak tanır.

Android görünüm animasyonları dahili olarak Koreografı aynı amaçla kullanır: animasyonları düzgün bir şekilde zamanlamak ve muhtemelen performansı artırmak için.

Koreograf her vsync olayı hakkında söylendiğinden, Koreograf.post * apis tarafından geçirilen Runnable'lardan birinin bir karenin zamanında bitip bitmediğini ve karelerin atlanmasına neden olduğunu söyleyebilirim.

Anladığım kadarıyla Koreograf sadece çerçeve atlamayı algılayabilir. Bunun neden olduğunu söylemenin bir yolu yok.

“Uygulama ana iş parçacığında çok fazla iş yapıyor olabilir” mesajı. yanıltıcı olabilir.

Kaynak: Logcat Koreograf mesajları Anlamı

Neden endişelenmelisin

Bu mesaj android emülatörde açıldığında ve atlanan kare sayısı oldukça az olduğunda (<100), emülatörün yavaş olması için güvenli bir bahis oynayabilirsiniz - bu neredeyse her zaman olur. Ancak, kare sayısı atlanmış ve büyükse ve 300+ sıradaysa, kodunuzda ciddi bir sorun olabilir. Android cihazlar, ios ve windows cihazlarından farklı olarak çok çeşitli donanımlara sahiptir. RAM ve CPU değişir ve tüm cihazlarda makul bir performans ve kullanıcı deneyimi istiyorsanız, bu şeyi düzeltmeniz gerekir. Çerçeveler atlandığında kullanıcı arayüzü yavaş ve laggy olur, bu da istenen bir kullanıcı deneyimi değildir.

Nasıl düzeltilir?

Bunu düzeltmek, uzun işlem süresinin olabileceği veya muhtemelen gerçekleşebileceği düğümlerin tanımlanmasını gerektirir. En iyi yol, ana UI iş parçacığından ayrı bir iş parçacığında ne kadar küçük veya büyük olursa olsun tüm işlemleri yapmaktır. SQLite Veritabanından veriye erişmek veya bazı hardcore matematik yapmak ya da sadece bir diziyi sıralamak olsun - Farklı bir iş parçacığında yapın

Şimdi burada bir yakalama var, bu işlemleri yapmak için yeni bir iş parçacığı oluşturacak ve uygulamanızı çalıştırdığınızda, "Yalnızca bir görünüm hiyerarşisi oluşturan orijinal iş parçacığı görünümlerine dokunabilir" diyerek çökecektir. Android'de UI'nin sadece ana iş parçacığı veya UI iş parçacığı tarafından değiştirilebileceği bu gerçeği bilmeniz gerekir. Bunu yapmaya çalışan diğer iş parçacıkları başarısız olur ve bu hatayla çöker. Yapmanız gereken runOnUiThread içinde yeni bir Runnable oluşturmak ve bu runnable içinde UI ile ilgili tüm işlemleri yapmanız gerekir. Burada bir örnek bulun .

Yani ana iş parçacığı dışında veri işlemek için iş parçacığı ve Runnable var, başka ne var? Android'de UI iş parçacığında uzun süre işlemleri yapmayı sağlayan AsyncTask var. Bu, uygulamaların veri güdümlü veya web API'lı olduğu veya Canvas kullanarak oluşturulanlar gibi karmaşık UI'leri kullandığınızda en kullanışlıdır. AsyncTask'ın gücü, arka planda bir şeyler yapmanıza izin vermesidir ve işlemi yaptıktan sonra, herhangi bir gecikme etkisine neden olmadan UI üzerinde gerekli eylemleri yapabilirsiniz. Bu, AsyncTask'ın Aktivitenin UI iş parçacığından türetilmesinden kaynaklanır - AsyncTask aracılığıyla UI'de yaptığınız tüm işlemler, ana UI iş parçacığından farklı bir iş parçacığıdır, Kullanıcı etkileşimine engel yok.

Bu yüzden pürüzsüz android uygulamaları yapmak için bilmeniz gerekenler ve bildiğim kadarıyla her acemi konsolunda bu mesajı alıyor.


41
Sadece bir düğmeyi tıklarsam düğmenin arka plan görüntüsünün değiştirilemeyeceği bir uygulama var. Ben nasıl çok fazla iş yapıyorum :(
Remian8985

1
@ Remian8985 - Düğmenin arka plan görüntüsü değişikliği (bu görüntüyü indirdiğinizi varsayarak) bir AsyncTask'ta yapılmalıdır - yani bu indirme arka plan işlemini gerçekleştirmek ve sonucu UI iş parçacığında yayınlamak (görüntüyü geri sağlamak). Android Referans linkine
BenJaminSila

11
AsyncTask'ta arka plan değişiyor mu? Gerçekten mi?
user25

11
@ user25 "Bu resmi indirdiğinizi varsayarak"
forresthopkinsa

"Bu mesaj android emülatörde açıldığında ve atlanan kare sayısı oldukça az olduğunda (<100) emülatörün yavaş olduğundan emin olabilirsiniz" Bugün hala geçerli mi? Emülatörler oldukça hızlı hale geliyor değil mi?
Robin Dijkhof

243

Diğerlerinin yukarıda yanıtladığı gibi, "55 kare atlandı!" uygulamanızda ağır işlemlerin olduğu anlamına gelir.

Benim durumumda, başvurumda ağır bir süreç yok. Ben çift ve üçlü her şeyi kontrol ve biraz ağır olduğunu düşünüyorum bu işlemi kaldırıldı.

Sadece iskelet kalana kadar Parçaları, Etkinlikleri, Kütüphaneleri kaldırdım. Ama yine de sorun ortadan kalkmadı. Kaynakları kontrol etmeye karar verdim ve kullandığım bazı ikonların ve arka planların oldukça büyük olduğunu gördüm, çünkü bu kaynakların boyutunu kontrol etmeyi unuttum.

Yani, benim önerim yukarıdaki cevapların hiçbiri yardımcı olmazsa, kaynak dosyalarınızın boyutunu da kontrol edebilirsiniz.


1
Benim için de çalıştı. Çok az iş yapan ama yavaş ve laggy bir uygulama vardı. Çerçeve günlüklerini atlamaya devam ettim. Etkinliğimden arka planı kaldırdığımda her şey yolundaydı. Teşekkürler!
akrabi

Harika cevap, bunun tam olarak benim sorunum olduğuna inanıyorum. Diğer (oldukça ilgili) çözümler bir demet denedim ve uygulama kadar yavaştı. Tüm web hizmetlerini çıkardım ve kodumu kemiğe göre optimize etmeye çalıştım. İşe yaramadı, o zaman bunu gördüm. Arka plan resmimi (sahip olduğum en büyük resim) kaldırır kaldırmaz, uygulama eski "yavaş" kodla bile, tıklayabildiğiniz kadar hızlı çalışır.
M Barbosa

günümü gün ettin!
Nicolas Mastromarino

:) Sen haksız bir dahisin.
Metin Ilhan

@batsheva 1 KB olmak gerekli değildir. İhtiyaçlarınıza bağlıdır, daha net bir görüntüye ihtiyacınız olduğunu varsayalım, daha yüksek çözünürlük kullanabilirsiniz, ancak farklı boyutlara kaynakların farklı klasörlerine bölündüğünüzden emin olun.
Sithu

61

Ben de aynı problemi yaşadım.
Mine çekilebilir bir arka plan görüntüsü kullandığım bir durumdu.Bu belirli görüntü yaklaşık 130kB idi ve benim android app açılış ekranı ve ana sayfa sırasında kullanıldı.

Çözüm - Ben sadece belirli bir resim drawables-drawable-xxx klasörüne kaydırdı ve arka planda işgal bellek bir sürü boş edebildi ve atlama çerçeveleri artık atlama değildi.

Güncelleme Arka plan çekilebilir dosyalarını saklamak için 'nodp' çekilebilir kaynak klasörünü kullanın.
Yoğunlukta nitelendirilebilir çekilebilir klasör veya çekilebilir nodpi öncelikli olacak mı?


7
Benim büyük arka plan görüntüsü mimap-xxxhdpi çekilebilir taşındı ve hile yaptı!
bgplaya

Çok yardım ettin. Teşekkürler
N.Droid

2
Bu çözüm hile yapıyor. Kullanılan belleği (~ yüzde 70 daha az) önemli ölçüde azaltan klasör drawable-xxxhdpiyerine kullanıyorum drawable. Ayrıca, aynı boyutta ekranların DPI boyutunda değiştiğini bilmek de iyidir. Aralarında piksel olarak oranı ldpi = 1:0.75, mdpi = 1:1, hdpi = 1:1.5, xhdpi = 1:2, xxhdpi = 1:3, xxxhdpi = 1:4. drawable-xxxhdpiKlasörü kullanarak, görüntüleri cihazınızın ekranlarına küçülterek bellek ve CPU tüketimini azaltan boyutlara sahip olursunuz.
Timo Bähr

2
Görüntüleri Hareketli drawableiçin drawable-nodpiulaşmasını engeller uygulaması Out of Memory Error.
Shruti

Aman tanrım ... teşekkürler! Çekilebilir klasör içinde bir görüntü vardı ve bu (görüntü sadece 100kb olmasına rağmen !!!) benim app cehennem gibi yavaş yaptı. Drawable-xxx dosyaları oluşturduktan sonra (Android Drawable Importer'ı kullandım) uygulamam çok hızlı. Çok teşekkürler!
error1337

20

UI iş parçacığında gecikmelerin bir diğer yaygın nedeni SharedPreferences erişimidir. A PreferenceManager.getSharedPreferencesve diğer benzer yöntemleri ilk kez çağırdığınızda , ilişkili .xml dosyası hemen aynı iş parçacığına yüklenir ve ayrıştırılır .

Bu sorunla mücadele etmenin iyi yollarından biri, mümkün olduğunca erken başlatılan (örneğin onCreateUygulama sınıfınızdan) arka plan iş parçacığından ilk SharedPreference yükünü tetiklemektir . Bu şekilde tercih nesnesi, kullanmak istediğiniz zamana kadar önceden oluşturulmuş olabilir.

Ne yazık ki, bazen başlangıç ​​dosyalarının erken aşamalarında tercih dosyalarının okunması gerekir (örn. İlk Faaliyette ve hatta Uygulamanın kendisinde). Bu gibi durumlarda hala kullanıcı arabirimini kullanarak durmaktan kaçınmak mümkündür MessageQueue.IdleHandler. Ana iş parçacığında gerçekleştirmeniz gereken her şeyi yapın, ardından Aktiviteniz tamamen çizildikten sonra kodu çalıştırmak için IdleHandler'ı yükleyin. Bu Runnable'da çok fazla çizim işlemini geciktirmeden ve Koreografı mutsuz yapmadan SharedPreferences'a erişebilmelisiniz.


1
Bu durumda, commit () yerine Apply () yöntemini tercih etmelisiniz. Apply () yöntemi kullanıcı arayüzünü engelleyemez. Buradan geliştirici.android.com/
Emre Gürses

16

Uygulama performansınızı artırmak için aşağıdaki stratejileri kullanmaya çalışın:

  • Mümkünse çok iş parçacıklı programlama kullanın. Akıllı telefonunuzun bir çekirdeği olsa bile performans avantajları çok büyüktür (işlemcinin iki veya daha fazla olması durumunda dişler farklı çekirdeklerde çalışabilir). Uygulama mantığınızı kullanıcı arayüzünden ayırmak yararlıdır. Java iş parçacıklarını, AsyncTask veya IntentService kullanın. Bunu kontrol et .
  • Android geliştirme web sitesinin çeşitli performans ipuçlarını okuyun ve takip edin. Buradan kontrol edin .

3
ilk bağlantınıza erişmek için "... doğrulanmış bir hesabınız ..." olmasını gerektirir.
chornge

9

Ben de aynı problemi yaşadım. Android Emulator Android <6.0'da mükemmel çalıştı. Emulator Nexus 5'i (Android 6.0) kullandığımda, uygulama I/Choreographer: Skipped framesgünlüklerde çok yavaş çalıştı .

Yani, bu sorunu çözmek için Manifest dosya hardwareAcceleratedseçeneğinde değiştirerek çözdüm 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

Uzman değilim, ama android uygulamamdan bir web sunucusuna veri göndermek istediğimde bu hata ayıklama mesajını aldım. AsyncTask sınıfını kullandım ve veri aktarımını arka planda yaptım, sonuç verilerini sunucudan geri almak için, UI'yi senkronize yapan AsyncTask sınıfının get () yöntemini kullandım, bu da UI'nizin çok uzun süre bekleyeceği anlamına geliyor. Bu yüzden tavsiyem, uygulamanızın her ağ odaklı görevi ayrı bir iş parçacığında yapmasını sağlamaktır.


6

Görüntülerinizi optimize edin ... 100 KB'den daha büyük görüntüler kullanmayın ... Görüntü yükleme çok fazla CPU gerektirir ve uygulamanızın askıda kalmasına neden olur.


4
Java koduyla görüntünün boyutunu
küçültün

5

Ben de aynı problemi yaşadım. Benim durumumda 2 iç içe Göreli Düzen vardı. RelativeLayout her zaman iki ölçü geçişi yapmak zorundadır. RelativeLayouts'u iç içe yerleştirirseniz, üstel bir ölçüm algoritması alırsınız.


4

bu genellikle ana iş parçacığında büyük işlemler yürütürken olur. 200'den az kareyi atlamak uygundur. Ancak 200'den fazla atlanmış kareniz varsa, uygulama UI iş parçacığını yavaşlatabilir. Yapabileceğiniz şey, bu işlemleri işçi iş parçacığı olarak adlandırılan yeni iş parçacığında yapmaktır ve bundan sonra, UI iş parçacığına erişmek ve sth yapmak istediğinizde (ör: görünümlerle bir şeyler yapın, findView vb ...) işleyici veya runOnUiThread kullanabilirsiniz İşlem sonuçlarını görüntülemek için (bunu daha çok seviyorum). bu kesinlikle sorunu çözer. işçi iş parçacığı kullanmak çok faydalıdır veya bu durum söz konusu olduğunda kullanılmalıdır.


1

Ben de aynı problemi yaşadım. Kodu başka bir bilgisayarda çalıştırdığımda iyi çalıştı. Ancak benimkinde "Uygulama ana iş parçacığında çok fazla iş yapıyor olabilir" ifadesini kullandı.

Android studio'yu yeniden başlatarak sorunumu çözdüm [Dosya -> Geçersiz önbellekler / Yeniden Başlat -> "Geçersiz ve Yeniden Başlat" ı tıklayın.


Çözümünüzün neden işe yaradığını bilmiyorum. Neyse teşekkürler.
Bhuvanesh BS

1

Benim durumumda, bir yönteme yanlışlıkla bir kesme noktası ayarlamıştım. Bir kez temizledikten sonra mesaj kayboldu ve performans çok gelişti.


0

Uygulamamda da aynı sorun vardı. Ancak kartların ve metinlerin listesini görüntülemek dışında bir şey yapmıyordu. Arka planda çalışan bir şey yok. Ancak daha sonra bazı araştırmalar, kart arka planı için ayarlanan görüntünün, küçük olmasına rağmen buna neden olduğunu buldu (350kb). Sonra http://romannurik.github.io/AndroidAssetStudio/index.html kullanarak görüntüyü 9 toplu görüntülere dönüştürdüm .
Bu benim için çalıştı.


0

Bu konuda çok Ar-Ge yaptıktan sonra Çözümü aldım,

Benim durumumda her 2 saniyede bir çalışacak hizmet kullanıyorum ve runonUIThread ile, sorunun orada ama hiç merak ediyorum. Bulduğum bir sonraki sorun, ben büyük bir görüntü App ve şu thats kullanıyorum olmasıdır.

Görüntüleri kaldırdım ve yeni Görüntüler ayarladım.

Sonuç: - Kodunuza bakın, kullandığınız herhangi bir ham dosya büyük boyuttadır.


0

Önce uyarıyı okuyun. Ana diş üzerinde daha fazla yük olduğunu söylüyor. Yani yapmanız gereken sadece bir iş parçacığında daha fazla iş ile fonksiyonları çalıştırmak.


-1

Izgara düzeninde çok sayıda çekilebilir png dosyası kullanan bir uygulama geliştirirken de aynı sorunu yaşadım. Ayrıca kodumu mümkün olduğunca optimize etmeye çalıştım .. ama benim için işe yaramadı .. Sonra bu png boyutunu azaltmak için çalıştı ve kesinlikle iyi çalışıyor sanırım .. Yani benim önerim azaltmak varsa çekilebilir kaynakların büyüklüğü ..

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.