Yavaş oluşturma

Kullanıcı arayüzü oluşturma, uygulamanızdan bir kare oluşturup bunu ekranda görebilirsiniz. Kullanıcıların uygulamanızla sorunsuz bir şekilde etkileşim kurmasına yardımcı olmak için 60 kare/saniye (fps) değerine ulaşması için uygulamanızın kareleri 16 ms.den kısa bir sürede oluşturması gerekir. 60 fps'nin neden tercih edildiğini anlamak için Android Performans Kalıpları: Neden 60 fps?? Yeni bir web sitesi için 90 fps'ye ulaşırsa bu pencere 11 ms'ye düşer ve 120 fps'de 8ms.

Bu pencereyi 1 ms. aşmanız, çerçevenin gösterileceği anlamına gelmez. 1 ms. geç kaldınız ancak Choreographer. çerçeveyi tamamen bırakır. Uygulamanızda yavaş kullanıcı arayüzü oluşturma sorunu yaşıyorsanız sistemimiz kareleri atlamaya zorlanır ve kullanıcı, uygulamanızda takılmayı algılar. Buna jank denir. Bu sayfada, olumsuzlukların nasıl teşhis edileceği ve düzeltileceği gösterilmektedir.

View sistemini, o zaman Choreographer. Bu örnekte, Çerçeve Hızı Kitaplık size yardımcı olur OpenGL ve Vulkan oyunları sorunsuz bir şekilde oluşturulur ve doğru kare hızını ayarlayın.

Android, uygulama kalitesini iyileştirmeye yardımcı olmak için uygulamanızı olumsuzluklara karşı otomatik olarak izler ve bilgileri Android vitals kontrol panelinde görüntüler. Daha fazla bilgi için hakkında daha fazla bilgi için Uygulamanızın teknik kalitesini Android hayati bulgular.

Riski tanımlama

Uygulamanızda jank'a neden olan kodu bulmak zor olabilir. Bu bölüm lekeyi tespit etmek için üç yöntem açıklanmaktadır:

Görsel inceleme, uygulamanızdaki tüm kullanım alanlarını birkaç saniyede inceleyebilmenizi sağlar. ancak Systrace kadar ayrıntı sağlamaz. Systrace, içerir ama uygulamanızdaki tüm kullanım alanları için Systrace'i çalıştırırsanız analiz edilmesi zor olabilen çok fazla veriyle bombardım. Hem görsel Systrace, yerel cihazınızda kirlilik olup olmadığını tespit eder. Yeniden oluşturamıyorsanız yerel cihazlarda oluşabilecek olumsuzlukları ölçmek için özel performans izleme uygulamanızın belirli bölümlerinden yararlanmanız gerekir.

Görsel inceleme

Görsel inceleme, olumsuzluk yaratan kullanım alanlarını belirlemenize yardımcı olur. Alıcı: uygulamanızı açın ve farklı adımları manuel olarak inceleyin, belirli bölümlerini kontrol edebilir ve kullanıcı arayüzünde sorun olup olmadığını kontrol edebilirsiniz.

Görsel inceleme gerçekleştirmeyle ilgili bazı ipuçları aşağıda verilmiştir:

  • Uygulamanızın sürümünü (veya en azından hata ayıklama yapılamayan bir sürümünü) çalıştırın. SANAT çalışma zamanı, hata ayıklamayı desteklemek için bazı önemli optimizasyonu devre dışı bırakır Bu nedenle, kullanıcı deneyiminin veya uygulamanızın görür.
  • Profil GPU'sunu etkinleştir Oluşturma. Profil GPU Oluşturma Aracı, ekranda size görsel bir görsel sunan çubuklar gösterir bir kullanıcı arayüzü penceresinin karelerini oluşturmak için ne kadar zaman gerektiğini gösteren gösterim ve çerçeve başına 16 ms. Her çubuğun renkli bileşenleri vardır Bu, görüntü oluşturma ardışık düzenindeki bir aşamayla eşlenir. Böylece hangi bölümün en uzun sürüyor. Örneğin, karede çok fazla zaman geçiriliyorsa kullanıcı girişini işleyen uygulama kodunuza bakın.
  • Örneğin, yaygın sorun kaynakları olan bileşenleri RecyclerView olarak.
  • Uygulamayı soğuk bir ortamdan başlangıç.
  • Sorunu artırmak için uygulamanızı daha yavaş bir cihazda çalıştırın.

Kötüye kullanım yaratan kullanım alanları bulduğunuzda, bunların ne tür bir sorun neden olur. Daha fazla bilgiye ihtiyacınız varsa Systrace'i kullanabilirsiniz. araştırmaya odaklanın.

Sistrace

Systrace tüm cihazın yaptığı işlemleri gösteren bir araç olsa da uygulamanızdaki olumsuzlukların tanımlanmasına yardımcı olur. Systrace'in sistemi minimum düzeyde Böylece enstrümantasyon sırasında gerçekçi bir titreme deneyimi yaşayabilirsiniz.

Systrace ile motive olacak bir uygulama seçeneğine sahip olursunuz. Systrace'in nasıl kullanılacağıyla ilgili talimatlar için bkz. Komut satırında sistem izleme kodunu yakalayın. Systrace süreçlere ve ileti dizileri. Systrace'te uygulamanızın sürecini arayın. Bu işlem aşağıdakine benzer: Şekil 1.

Systrace örneği
Şekil 1. Systrace örneği.

Şekil 1'deki Systrace örneği , aşağıdaki bilgileri içerir: tespit eden olumsuzlukları tespit etme:

  1. Systrace, her karenin ne zaman çizildiğini gösterir ve her kareyi farklı renklere yavaş oluşturma sürelerini vurgular. Bu, her bir tuhaf kareyi daha çok daha doğru sonuçlar verir. Daha fazla bilgi için bkz. Kullanıcı arayüzünü inceleme çerçeveler ve uyarılar hakkında daha fazla bilgi edinin.
  2. Systrace, uygulamanızdaki sorunları algılar ve her ikisinde de uyarıları gösterir. bağımsız çerçeveler ve uyarılar panelini açın. Uyarıdaki talimatları uygulamanız önerilir.
  3. Android çerçevesinin ve kitaplıklarının bazı bölümleri RecyclerView, iz işaretçileri içeriyor. Dolayısıyla, systrace zaman çizelgesi, bu yöntemlerin kullanıcı arayüzünde ne zaman yürütüldüğünü gösterir yürütmenin ne kadar sürdüğünü gösterir.

Systrace çıkışına baktıktan sonra uygulamanızda sizi olabilir. Örneğin, zaman çizelgesinde yavaş bir karenin RecyclerView uzun sürmesinden kaynaklanıyorsa özel iz ekleyebilirsiniz ve etkinlikleri ilgili koda daha fazla bilgi için Systrace'i yeniden çalıştırın. Yeni Systrace'te zaman çizelgesi yöntemlerinin ne zaman çağrıldığı ve ne kadar sürede çalıştırıldığı.

Systrace, kullanıcı arayüzü iş parçacığı çalışmasının neden uzun sürdüğüyle ilgili ayrıntıları göstermezse kullanın, ardından Android CPU Profil oluşturucu yöntem izler. Yöntem izleri genelde şiddeti nedeniyle yanlış pozitif olumsuz etkiler ürettiği için ve ileti dizilerinin ne zaman çalıştığını ve ne zaman engellendiğini göremez. Ancak, yöntem izleri, uygulamanızda sakıncalı içerik barındıran yöntemleri belirlemenize çok önemli. Bu yöntemleri belirledikten sonra Trace işaretçileri seçin ve Systrace'i yeniden olup olmadığını kontrol edebilirsiniz.

Daha fazla bilgi için bkz. Anlama Systrace.

Özel performans izleme

Chat'i yerel cihazda yeniden oluşturamıyorsanız özel performans sitenizdeki olumsuzlukların kaynağını belirlemenize yardımcı olmak için uygulamanızı izlemenizi öneririz. girin.

Bunun için uygulamanızın belirli bölümlerindeki kare oluşturma sürelerini toplamak için FrameMetricsAggregator Firebase Performans'ı kullanarak verileri kaydedip analiz edin İzleme.

Daha fazla bilgi için Android.

Donmuş kare

Donmuş kareler, oluşturulması 700 ms'den uzun süren kullanıcı arayüzü kareleridir. Bu, Sorun, uygulamanızın takılıp kaldığı ve kullanıcı girişine yanıt vermediği için yaklaşık bir saniyeliğine ekranda kalır. Önerilerimiz uygulamalarını 16 ms içinde bir kare oluşturarak sorunsuz bir kullanıcı arayüzü sağlar. Ancak, uygulama sırasında başlatın veya farklı bir ekrana geçiş yaparken, uygulamanızın şişirmesi gerektiğinden ilk karenin çizim için 16 ms'den uzun sürmesi ekranı yerleştirin ve ilk çizimi baştan yapın. Bu yüzden Android, donmuş kareleri yavaş oluşturma işleminden ayrı olarak izler. Sıra No: uygulamanızdaki karelerin oluşturulması 700 ms'den uzun sürer.

Android, uygulama kalitesini iyileştirmenize yardımcı olmak için uygulamanızı donmuş kareleri görüntüler ve Android vitals kontrol panelinde bilgileri gösterir. Verilerin nasıl toplandığı hakkında bilgi için Uygulamanızın teknik verilerini izleme kaliteyi test edin.

Donmuş kareler, yavaş oluşturmanın aşırı bir biçimidir. Dolayısıyla, sorunu teşhis etme ve düzeltme prosedürü aynıdır.

olumsuzlukları takip etme

Kare Zaman Çizelgesi Perfetto'nun yardımıyla yavaş veya donmuş kareler.

Yavaş kareler, donmuş kareler ve ANR'ler arasındaki ilişki

Yavaş kareler, donmuş kareler ve ANR'ler, sitenizin veya oyununuzun karşılaşabileceği durumlar. Farkı anlamak için aşağıdaki tabloya bakın.

Yavaş kare sayısı Donmuş kare ANR'ler
Oluşturma süresi 16 ms ile 700 ms arasında 700 ms ile 5 sn arasında 5 saniyeden fazla
Görünür kullanıcı etki alanı
  • RecyclerView kaydırma çubuğu aniden çalışıyor
  • Karmaşık animasyonların düzgün şekilde animasyon gösterilmediği ekranlarda
  • Uygulama başlatılırken
  • Bir ekrandan başka bir ekrana (ör. ekran) geçme geçiş
  • Etkinliğiniz ön plandayken uygulamanız yanıt vermedi bir giriş etkinliğine veya BroadcastReceiver öğesine basın (tuşa basma veya beş saniye içinde ekranda dokunma etkinlikleri gösteriliyor.
  • Ön planda bir etkinliğiniz olmasa da BroadcastReceiver, yürütme işlemini şu süre içinde tamamlamadı: önemli bir süre.

Yavaş kareleri ve donmuş kareleri ayrı ayrı takip edin

Uygulama başlatılırken veya farklı bir ekrana geçerken ilk karenin çizim için 16 ms'den uzun sürmesini görüntüleri şişirin, ekranı yerleştirin ve ilk çizimi sıfırdan yapın.

Arızaları önceliklendirme ve çözmeyle ilgili en iyi uygulamalar

Hesabınızdaki sakıncaları giderirken aşağıdaki en iyi uygulamaları aklınızda bulundurun uygulama:

  • En kolay yeniden üretilebilir jank örneklerini belirleyin ve çözün.
  • ANR'lere öncelik ver. Yavaş veya donmuş kareler bir uygulamanın gösterilmesine neden olabilir. yavaşsa ANR'ler uygulamanın yanıt vermemesine neden olur.
  • Yavaş oluşturma işleminin yeniden oluşturulması zordur ancak donmuş 700 ms. değerini sonlandırarak başlayabilirsiniz çerçeveler. Bu durum en çok uygulama açılırken veya ekranı değiştirirken görülür.

Düzeltme sorunu

Titremeyi düzeltmek için 16 ms'de hangi karelerin tamamlanmadığını inceleyin ve yanlış. Record View#draw veya Layout sürecinin anormal derecede uzun sürdüğünü kontrol edin bazı kareler. Bu sorunlar ve diğerleri.

Aksaklıklardan kaçınmak için uzun süreli görevleri, kullanıcı arayüzü iş parçacığı dışında eşzamansız olarak çalıştırın. Kodunuzun hangi iş parçacığı üzerinde çalıştığına her zaman dikkat edin ve önemsiz görevleri ana ileti dizisine gönderme.

Uygulamanız için karmaşık ve önemli bir birincil kullanıcı arayüzünüz varsa (örneğin, kaydırma listesi; yazma araçlarını kullanmayı düşünün otomatik olarak Yavaş oluşturma sürelerini tespit edip testleri sık sık çalıştırarak regresyonları önleyin.

Yaygın olumsuzluk kaynakları

Aşağıdaki bölümlerde, View kullanan uygulamalarda yaygın olumsuzluk kaynakları açıklanmaktadır en iyi uygulamaları paylaşıyoruz. Sorunu düzeltme hakkında bilgi için Jetpack Compose ile ilgili performans sorunları hakkında bilgi edinin (Jetpack). Performansı oluşturun.

Kaydırılabilir listeler

ListView ve özellikle RecyclerView—genellikle en çok kullanılan karmaşık kaydırma listeleri için kullanılır riske açıktır. İkisi de Systrace işaretçileri içerdiğinden Systrace'i olup olmadığını kontrol edebilirsiniz. Komut satırını aktarma RecyclerView içindeki iz bölümlerini almak için -a <your-package-name> bağımsız değişkeni ve tüm görünür. Varsa Systrace çıkışında oluşturulan uyarılar. Systrace'in içinde, Çalışmanın açıklamasını görmek için RecyclerView izlenen bölümler RecyclerView yapıyor.

RecyclerView: notificationDataSetChanged()

RecyclerView içindeki her öğenin ribaundulup tekrar sıralandığını görürseniz ve tek bir karede yeniden çizilir. Aramayı gerçekleştirmediğinizden emin olun. notifyDataSetChanged(), setAdapter(Adapter) veya swapAdapter(Adapter, boolean) . Bu yöntemler, reklam grubunun tamamında veya içeriği listelemeli ve Systrace'te RV FullInValidate olarak görünür. Bunun yerine SortedList veya Oluşturmak için DiffUtil İçerik değiştirildiğinde veya eklendiğinde minimum güncelleme yapılması.

Örneğin, bir haber listesinin yeni sürümünü alan bir uygulamayı ele alalım. bir sunucudan alınır. Bu bilgileri Bağdaştırıcıya yayınladığınızda aşağıdaki örnekte gösterildiği gibi notifyDataSetChanged() çağrılması mümkündür:

Kotlin

fun onNewDataArrived(news: List<News>) {
    myAdapter.news = news
    myAdapter.notifyDataSetChanged()
}

Java

void onNewDataArrived(List<News> news) {
    myAdapter.setNews(news);
    myAdapter.notifyDataSetChanged();
}

Bunun olumsuz tarafı, tek bir öğe gibi küçük bir değişiklik olmasıdır. üst kısmına eklendiğinde RecyclerView algılanmaz. Bu nedenle, tüm önbelleğe alınmış öğe durumu ve bu nedenle her şeyi yeniden bağlaması gerekir.

Minimum güncellemeleri hesaplayıp gönderen DiffUtil kullanmanızı öneririz. sizin için:

Kotlin

fun onNewDataArrived(news: List<News>) {
    val oldNews = myAdapter.items
    val result = DiffUtil.calculateDiff(MyCallback(oldNews, news))
    myAdapter.news = news
    result.dispatchUpdatesTo(myAdapter)
}

Java

void onNewDataArrived(List<News> news) {
    List<News> oldNews = myAdapter.getItems();
    DiffResult result = DiffUtil.calculateDiff(new MyCallback(oldNews, news));
    myAdapter.setNews(news);
    result.dispatchUpdatesTo(myAdapter);
}

DiffUtil hizmetinin listelerinizi nasıl inceleyeceği hakkında bilgi vermek için MyCallback öğenizi Callback bazı ipuçları vereceğim.

RecyclerView: Nested RecyclerView

RecyclerView öğesinin birden fazla örneğini iç içe yerleştirmek yaygın bir durumdur. Özellikle Yatay olarak kaydırılan listelerin dikey listesi. Bu duruma örnek olarak Play Store ana sayfasında görebilirsiniz. Bu çok işe yarayabilir ancak aynı zamanda farklı açılardan görebilirsiniz.

Sayfayı ilk kez aşağı kaydırdığınızda iç öğelerin çok daha genişlediğini görürseniz paylaşıp paylaşmadığınızı kontrol etmek isteyebilirsiniz RecyclerView.RecycledViewPool RecyclerView öğesinin iç (yatay) örnekleri arasında. Varsayılan olarak RecyclerView kendi öğe havuzuna sahiptir. Ancak durumunda, 100 itemViews ekranda aynı anda gösteriliyor ve itemViews tarafından görüntülenemez. tüm satırlar benzer görünüyorsa farklı yatay listeler tarafından paylaşılacaktır izin verebilirsiniz.

Kotlin

class OuterAdapter : RecyclerView.Adapter<OuterAdapter.ViewHolder>() {

    ...

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        // Inflate inner item, find innerRecyclerView by ID.
        val innerLLM = LinearLayoutManager(parent.context, LinearLayoutManager.HORIZONTAL, false)
        innerRv.apply {
            layoutManager = innerLLM
            recycledViewPool = sharedPool
        }
        return OuterAdapter.ViewHolder(innerRv)
    }
    ...

Java

class OuterAdapter extends RecyclerView.Adapter<OuterAdapter.ViewHolder> {
    RecyclerView.RecycledViewPool sharedPool = new RecyclerView.RecycledViewPool();

    ...

    @Override
    public void onCreateViewHolder(ViewGroup parent, int viewType) {
        // Inflate inner item, find innerRecyclerView by ID.
        LinearLayoutManager innerLLM = new LinearLayoutManager(parent.getContext(),
                LinearLayoutManager.HORIZONTAL);
        innerRv.setLayoutManager(innerLLM);
        innerRv.setRecycledViewPool(sharedPool);
        return new OuterAdapter.ViewHolder(innerRv);

    }
    ...

Daha fazla optimizasyon yapmak isterseniz setInitialPrefetchItemCount(int) uygulamasında LinearLayoutManagerRecyclerView iç boşluğu. Örneğin, her zaman 3, 5 öğeniz varsa art arda innerLLM.setInitialItemPrefetchCount(4) numaralı telefonu arayın. Bu, trafiğin RecyclerView: Yatay bir satır ekrana gelmek üzereyken kullanıcı arayüzü iş parçacığında boş zaman varsa içerideki öğeleri önceden getirmeyi deneyin.

RecyclerView: Çok fazla yansıtma veya oluşturma işlemi çok uzun sürüyor

Çoğu durumda, RecyclerView hizmetindeki önceden getirme özelliği enflasyon maliyetini ortadan kaldırmak da mümkündür. Bir çerçeve sırasında ve karavan etiketli bir bölümde şişirme görüyorsanız Önceden getirme, desteklenen bir cihazda test yaptığınızdan ve Destek Kitaplığı sürümü. Önceden getirme yalnızca Android 5.0 API Düzeyi 21 ve sonraki sürümlerde desteklenir.

Yeni öğeler ekranda görünce sıklıkla enflasyonun olumsuz etkilere neden olduğunu görüyorsanız ekranda yeni öğeler olduğunu doğrulayın. sahip olduğunuzdan emin olun. Görüntüleme türü ne kadar içerik RecyclerView ise, yeni içerikler üretildiğinde daha az ekranda görünür. Mümkünse görünüm türlerini birleştirin. Eğer türler arasında yalnızca bir simge, renk veya metin parçası değiştiğinde, bağlama zamanında değişerek uygulamanızın belleğini azaltan aşırıya kaçmayın sahip olması gerekir.

Görüntüleme türleriniz iyi görünüyorsa enflasyonunuzun maliyetini düşürebilirsiniz. Gereksiz container ve yapısal görünümlerin azaltılması işe yarayabilir. Derlemeyi düşünün ConstraintLayout ile itemViews, Bu da yapısal görünümleri azaltmaya yardımcı olabilir.

Performans için daha fazla optimizasyon yapmak istiyorsanız ve öğe hiyerarşileriniz basit ve karmaşık temalar ile stil özelliklerine ihtiyacınız yoksa tasarımcıları araştırmalısınız. Ancak çoğu zaman, kaybetmenin bedelini XML'in basitliği ve özellikleri.

RecyclerView: Bağlama işlemi çok uzun sürüyor

onBindViewHolder(VH, int) bağlama işleminin basit olması gerekir ve ancak en karmaşık öğeler hariç her şey. Düz eski Java nesnesini (POJO) almalıdır ve bağdaştırıcınızın dahili öğe verilerindeki öğeler ile ViewHolder RV OnBindView işlemi uzun sürüyorsa bağlantı kodunuzda minimum düzeyde iş yapmanıza olanak tanır.

Bağdaştırıcınızda veri tutmak için temel POJO nesnelerini kullanıyorsanız bağlama kodunu onBindViewHolder dilinde yazmaktan tamamen kaçının. Bunun için Veri Bağlama Kitaplığı.

RecyclerView veya ListView: Düzen veya çizim çok uzun sürüyor

Çizim ve düzen sorunları için şu konulara bakın: Düzen performansı ve Oluşturma performansı bölümleri.

ListView: Enflasyon

Dikkatli olmazsanız ListView içinde geri dönüşümü yanlışlıkla devre dışı bırakabilirsiniz. Eğer bir öğe ekranda her göründüğünde enflasyon görüyorsanız, uygulanması Adapter.getView() derinine inmek, yeniden bağlama ve convertView parametresini döndürüyor. Eğer getView() uygulaması her zaman şişiriyor, uygulamanız ListView bölgesinde geri dönüşüm. getView() yapısı hemen her zaman şu şekilde olmalıdır: aşağıdaki uygulamaya benzer:

Kotlin

fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
    return (convertView ?: layoutInflater.inflate(R.layout.my_layout, parent, false)).apply {
        // Bind content from position to convertView.
    }
}

Java

View getView(int position, View convertView, ViewGroup parent) {

    if (convertView == null) {
        // Only inflate if no convertView passed.
        convertView = layoutInflater.inflate(R.layout.my_layout, parent, false)
    }
    // Bind content from position to convertView.
    return convertView;
}

Düzen performansı

Systrace, Choreographer#doFrame öğesinin Düzen segmentinin çok sık veya çok fazla çalışıyorsa performans sorunları var. Uygulamanızın düzen performansı, uygulama düzeninin düzen parametreleri veya girişleri değişir.

Düzen performansı: Maliyet

Segmentler birkaç milisaniyeden uzunsa en kötü durum iç içe yerleştirme performansına RelativeLayouts veya weighted-LinearLayouts. Her biri bu düzenler, alt öğeleri için birden fazla ölçüm ve düzen geçişini tetikleyebilir. iç içe yerleştirmek, iç içe yerleştirmenin derinliğinde O(n^2) davranışına yol açabilir.

Aşağıdakiler dışında RelativeLayout veya LinearLayout ağırlık özelliğini kullanmamaya çalışın: yaprak düğümlerinden birini seçin. Bunu yapmanın yolları aşağıda açıklanmıştır:

  • Yapısal görünümlerinizi yeniden düzenleyin.
  • Özel düzen mantığını tanımlayın. Görüntüleyin Düzen hiyerarşilerini optimize etme inceleyebilirsiniz. Şuna dönüştürmeyi deneyebilirsiniz: ConstraintLayout, şunu sağlar: herhangi bir performans dezavantajı olmayan benzer özellikler sunuyor.

Düzen performansı: Sıklık

Düzen, ekranda yeni içerik göründüğünde (örneğin, RecyclerView görünümünde yeni bir öğe görünüme girer. Önemli düzen her karede gerçekleştiğinden, düzeni canlandırıyor olabilirsiniz. karelerin atılmasına neden olabilir.

Genellikle animasyonlar View öğesinin çizim özelliklerinde çalıştırılmalıdır. Örneğin, takip etmek için:

Bunların tamamını düzen özelliklerinden çok daha ucuza değiştirebilirsiniz. Örneğin, kenar boşlukları vardır. Genel olarak, e-posta adresini değiştirmek için özelliklerini tetikleyen bir ayarlayıcıyı çağırarak görünümün invalidate() ve ardından şu adım gelir: draw(Canvas) bir sonraki karede gösterilir. Bu komut, şu duran görünüm için çizim işlemlerini genellikle düzenden daha ucuzdur.

Oluşturma performansı

Android kullanıcı arayüzü iki aşamada çalışır:

  • Her gün draw(Canvas) çalıştıran kullanıcı arayüzü iş parçacığında View#draw olabilir ve çağrıları özel görünümlere veya kodunuza çağırabilir.
  • Yerel RenderThread üzerinde çalışan RenderThread üzerindeki DrawFrame ancak Record View#draw aşaması tarafından oluşturulan çalışmaya dayalı olarak çalışır.

Oluşturma performansı: Kullanıcı Arayüzü İş Parçacığı

Record View#draw uzun sürüyorsa bit eşlemler genellikle boyanıyor. Bit eşlem boyama işlemi için CPU oluşturma kullanılır. genellikle mümkün olduğunda bundan kaçınır. Android cihazınızda CPU Profiler'ı kontrol edin. düşünmeye başlamışsınızdır.

Bit eşlem boyama, genellikle bir uygulama bit eşlemi başka bir dosyadan önce düzeltmek istediğinde yapılır bazen yuvarlatılmış köşeler eklemek gibi bir süsleme yapabilirsiniz:

Kotlin

val paint = Paint().apply {
    isAntiAlias = true
}
Canvas(roundedOutputBitmap).apply {
    // Draw a round rect to define the shape:
    drawRoundRect(
            0f,
            0f,
            roundedOutputBitmap.width.toFloat(),
            roundedOutputBitmap.height.toFloat(),
            20f,
            20f,
            paint
    )
    paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.MULTIPLY)
    // Multiply content on top to make it rounded.
    drawBitmap(sourceBitmap, 0f, 0f, paint)
    setBitmap(null)
    // Now roundedOutputBitmap has sourceBitmap inside, but as a circle.
}

Java

Canvas bitmapCanvas = new Canvas(roundedOutputBitmap);
Paint paint = new Paint();
paint.setAntiAlias(true);
// Draw a round rect to define the shape:
bitmapCanvas.drawRoundRect(0, 0,
        roundedOutputBitmap.getWidth(), roundedOutputBitmap.getHeight(), 20, 20, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
// Multiply content on top to make it rounded.
bitmapCanvas.drawBitmap(sourceBitmap, 0, 0, paint);
bitmapCanvas.setBitmap(null);
// Now roundedOutputBitmap has sourceBitmap inside, but as a circle.

Bu işlem, UI iş parçacığı üzerinde yapılıyorsa bunu arka planda kod çözme iş parçacığı üzerinde yapacaksınız. Bazı durumlarda, Örneğin, işi çizim zamanında bile yapabilirsiniz. Örneğin, Drawable veya View kodu aşağıdaki gibi görünür:

Kotlin

fun setBitmap(bitmap: Bitmap) {
    mBitmap = bitmap
    invalidate()
}

override fun onDraw(canvas: Canvas) {
    canvas.drawBitmap(mBitmap, null, paint)
}

Java

void setBitmap(Bitmap bitmap) {
    mBitmap = bitmap;
    invalidate();
}

void onDraw(Canvas canvas) {
    canvas.drawBitmap(mBitmap, null, paint);
}

Bunu şununla değiştirebilirsiniz:

Kotlin

fun setBitmap(bitmap: Bitmap) {
    shaderPaint.shader = BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
    invalidate()
}

override fun onDraw(canvas: Canvas) {
    canvas.drawRoundRect(0f, 0f, width, height, 20f, 20f, shaderPaint)
}

Java

void setBitmap(Bitmap bitmap) {
    shaderPaint.setShader(
            new BitmapShader(bitmap, TileMode.CLAMP, TileMode.CLAMP));
    invalidate();
}

void onDraw(Canvas canvas) {
    canvas.drawRoundRect(0, 0, width, height, 20, 20, shaderPaint);
}

Bu işlemi arka plan koruması için de yapabilirsiniz. Örneğin gradyan bit eşlemin üzerine gelip resim filtrelemeyi ColorMatrixColorFilter - iki bit eşlemleri değiştirerek yapılan diğer yaygın işlemlerdir.

Bir bit eşlemi başka bir nedenle çiziyorsanız (muhtemelen onu bir önbellektir. View veyaCanvas Drawable doğrudan. Gerekirse, setLayerType() şununla: LAYER_TYPE_HARDWARE Böylece, karmaşık oluşturma çıkışını önbelleğe alabilir ve yine de GPU oluşturma özelliğinden yararlanabilirsiniz.

Oluşturma performansı: RenderThread

Bazı Canvas işlemlerini kaydetmek düşük maliyetlidir ancak pahalı hesaplamaları tetikler. RenderThread üzerinde. Systrace genellikle bunları uyarılarla belirtir.

Büyük Yollara Animasyon Oluşturma

Zaman Canvas.drawPath(), geçilen donanım hızlandırmalı Canvas üzerinde çağrılıyor View için Android bu yolları önce CPU'da çeker ve GPU'ya yükler. Büyük yollarınız varsa yolların kareden kareye doğru şekilde düzenlenmesinden kaçının. önbelleğe alınıp verimli bir şekilde çizilebilir. drawPoints() drawLines() ve drawRect/Circle/Oval/RoundRect() daha verimli ve daha fazla çizim çağrısı kullansanız bile daha iyi bir seçimdir.

Canvas.clipPath

clipPath(Path) pahalı kırpma davranışını tetikler ve genellikle bundan kaçınılmalıdır. Zaman Dikdörtgen olmayan boyutlara kırpmak yerine şekil çizmeyi tercih edin. Google daha iyi performans gösterir ve kenar yumuşatmayı destekler. Örneğin, clipPath çağrısı farklı şekilde ifade edilebilir:

Kotlin

canvas.apply {
    save()
    clipPath(circlePath)
    drawBitmap(bitmap, 0f, 0f, paint)
    restore()
}

Java

canvas.save();
canvas.clipPath(circlePath);
canvas.drawBitmap(bitmap, 0f, 0f, paint);
canvas.restore();

Bunun yerine, önceki örneği şu şekilde ifade edin:

Kotlin

paint.shader = BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
// At draw time:
canvas.drawPath(circlePath, mPaint)

Java

// One time init:
paint.setShader(new BitmapShader(bitmap, TileMode.CLAMP, TileMode.CLAMP));
// At draw time:
canvas.drawPath(circlePath, mPaint);
Bit eşlem yüklemeleri

Android, bit eşlemleri OpenGL dokuları olarak görüntüler ve bir bit eşlem ilk kez GPU'ya yüklenir. Bunu Systrace'te şu şekilde görebilirsiniz: Doku yüklemesi(id) genişliği x yükseklik. Bu işlem birkaç milisaniye sürebilir. ancak resmin GPU ile gösterilmesi gerekir.

Bu işlemler uzun sürüyorsa, önce genişlik ve yükseklik numaralarını kontrol edin. izler. Gösterilen bit eşlemin ekranda gösterildiği alanı belirler. Aksi takdirde, yükleme zamanını ve yer alır. Genellikle, bit eşlem yükleme kitaplıkları, bir uygun boyutta bit eşlem var.

Android 7.0'da, genellikle kitaplıklar tarafından yapılan bit eşlem yükleme kodu, prepareToDraw() - erken yüklemeyi tetikleyin. Bu sayede, yükleme işlemi daha RenderThread boştayken. Bu işlemi, kodu çözdükten sonra veya bağlama sırasında yapabilirsiniz. bilgi sahibi olduğunuz sürece, bir görünüm oluşturabilirsiniz. İdeal olarak, bit eşleminiz yüklediğiniz bit eşlemin bunu sizin yerinize yapar, ancak kendi kütüphanenizi yönetiyorsanız veya yeni cihazlarda yüklemelere basmazsanız prepareToDraw() numaralı telefonu kendi başınıza arayabilirsiniz girin.

Bir uygulama,
  çerçeve yükleme büyük bir bit eşlem
Şekil 2. Uygulama, bir karede önemli ölçüde zaman geçiriyor bir bit eşlem yüklemektir. Boyutunu küçültün ya da bu işlemi tamamladıktan sonra kodu prepareToDraw() ile çözün.

İş parçacığı planlama gecikmeleri

İş parçacığı planlayıcı, Android işletim sisteminin sistemde hangi iş parçacıklarının çalıştırılması gerektiğine, ne zaman ve ne kadar süreyle çalıştırılacağına karar verme.

Kilitlenmeler bazen uygulamanızın kullanıcı arayüzü iş parçacığının engellenmesi veya çalışmamasından kaynaklanır. Systrace, bir ileti dizisinin ne zaman oluşturulacağını belirtmek için Şekil 3'te gösterildiği gibi uyuyan (gri), çalıştırılabilir (mavi: koşabilir, ancak planlayıcı, aktif şekilde çalışıyor (yeşil) veya kesintisiz uykuda (kırmızı veya turuncu). Bu, istenmeyen e-postalarla ilgili Bunun nedeni, iş parçacığı planlama gecikmeleri olmasıdır.

Kullanıcı arayüzü iş parçacığının
  uyuyor
Şekil 3. Kullanıcı arayüzü iş parçacığının yardımcı olur.
ziyaret edin.

Çoğu zaman bağlayıcı çağrıları, Android: Uygulamanızın yürütülürken uzun süreli duraklamalara neden olur. Android'in sonraki sürümlerinde, kullanıcı arayüzü iş parçacığının çalışmayı durdurmasının en yaygın nedenlerinden biridir. Genel olarak çözüm, bağlayıcı çağrıları yapan işlevleri çağırmaktan kaçınmaktır. Eğer değeri önbelleğe alabilir veya çalışmayı arka plandaki ileti dizilerine taşıyabilirsiniz. Kod tabanı olarak bir bağlayıcı çağrısı ekleyebilirsiniz. Bunun için üst düzey yöntemini kullanabilirsiniz. Ancak bunları izlemeyi kullanarak bulabilir ve düzeltebilirsiniz.

Bağlayıcı işlemleriniz varsa bunların çağrı yığınlarını şu adb komutlarını uygulayın:

$ adb shell am trace-ipc start
… use the app - scroll/animate ...
$ adb shell am trace-ipc stop --dump-file /data/local/tmp/ipc-trace.txt
$ adb pull /data/local/tmp/ipc-trace.txt

Bazen zararsız görünen aramalar, getRefreshRate(), şunları yapabilir: bağlayıcı işlemlerini tetikler ve çağrıldıklarında büyük sorunlara alabilir. Düzenli aralıklarla takip etmek bu sorunları bulmanıza ve düzeltmenize görünebilir.

Bağlama nedeniyle uyuyan kullanıcı arayüzü iş parçacığını gösterir
  işlemleri gerçekleştirmiyor. Bağlama mantığınızın odağını koruyun ve aşağıdakileri yapmak için trace-ipc&#39;yi kullanın:
  bağlayıcı çağrılarını
izlemek ve kaldırmaktır.
Şekil 4. Kullanıcı arayüzü iş parçacığı, bağlayıcı nedeniyle uyuyor işlemleri gerçekleştirmiyor. Bağlama mantığınızı basit tutun ve Bağlayıcı çağrıları izlemek ve kaldırmak için trace-ipc.

Bağlayıcı etkinliği görmemenize rağmen hâlâ kullanıcı arayüzü iş parçacığınızın çalıştırıldığını görmüyorsanız başka bir iş parçacığından gelen bir kilitleme veya başka bir işlem beklemediğinizden emin olun. Genellikle, kullanıcı arayüzü iş parçacığının diğer iş parçacıklarından gelen sonuçları beklemesi gerekmez. Diğer ileti dizilerinde bilgi yayınlanması gerekir.

Nesne ayırma ve atık toplama

Nesne ayırma ve atık toplama (GC) sorun değil, önemli ölçüde daha az ART, Android 5.0'da varsayılan çalışma zamanı olarak kullanıma sunulduğundan beri ileti dizilerinizi titizleştirmenize yardımcı olur. Farklılıkları saniyede birçok kez gerçekleşmeyen nadir olaya tepki olarak ancak her ayırmanın bir maliyeti olduğunu unutmayın. Eğer sık çağrılan sıkı bir döngüdedir; bu nedenle, GC'deki yükü hafifletmek için kullanılır.

Systrace, GC'nin sık çalışıp çalışmadığını ve Android Belleğin Profiler, ayırmaların nerede olduğunu gösterebilir nereden geldiğidir. Mümkün olduğunda ayırmalardan kaçınıyorsanız, özellikle çok sıkışık takip ederseniz sorun yaşamazsınız.

HeapTaskDaemon&#39;da 94 ms GC gösterir
Şekil 5. HeapTaskDaemon'da 94 ms GC açın.

Android'in son sürümlerinde GC genellikle HeapTaskDaemon. Önemli miktarda tahsis, daha fazla CPU anlamına gelebilir GC için harcanan kaynak miktarı (Şekil 5'te gösterildiği gibi).

ziyaret edin.