View
nesnelerinizin hiyerarşisini yönetme şekliniz, uygulamanızın performansını önemli ölçüde etkileyebilir. Bu sayfada, görünüm hiyerarşinizin uygulamanızı yavaşlatıp yavaşlatmadığını nasıl değerlendireceğiniz açıklanmakta ve ortaya çıkabilecek sorunların çözümü için bazı stratejiler sunulmaktadır.
Bu sayfa, View
tabanlı düzenlerin iyileştirilmesine odaklanmaktadır. Jetpack Compose performansını iyileştirme hakkında bilgi için Jetpack Compose performansını inceleyin.
Performansı düzenleyin ve ölçün
Oluşturma ardışık düzeni, bir düzen ve ölçme aşaması içerir. Bu aşama sırasında sistem, görünüm hiyerarşinizdeki alakalı öğeleri uygun şekilde konumlandırır. Bu aşamanın ölçüm kısmı, View
nesnelerinin boyutlarını ve sınırlarını belirler. Düzen bölümü, View
nesnelerinin ekranın neresinde konumlanacağını belirler.
Bu ardışık düzen aşamalarının her ikisi de işledikleri görüntüleme veya düzen başına düşük bir maliyete neden olur. Çoğu zaman bu maliyet minimumdur ve performansı önemli ölçüde etkilemez. Ancak bir uygulama View
nesne eklediğinde veya kaldırdığında (örneğin, bir RecyclerView
nesne bunları geri dönüştürdüğünde veya yeniden kullandığında) daha büyük olabilir. View
nesnesinin kısıtlamalarını karşılamak için yeniden boyutlandırmayı düşünmesi gerektiğinde de maliyet daha yüksek olabilir. Örneğin, uygulamanız metni saran bir View
nesnesinde SetText()
çağrısı yaparsa View
öğesinin yeniden boyutlandırması gerekebilir.
Bu gibi durumlar çok uzun sürerse izin verilen 16 ms. içinde bir karenin oluşturulmasını engelleyebilir. Bu da karelerin düşmesine ve animasyonun kalitesinin düşmesine neden olabilir.
Bu işlemleri bir çalışan iş parçacığına taşıyamayacağınız için (uygulamanızın bunları ana iş parçacığında işlemesi gerekir) en iyi yöntem, işlemleri mümkün olduğunca az zaman alacak şekilde optimize etmektir.
Karmaşık düzenleri yönetin
Android Düzenler, kullanıcı arayüzü nesnelerini görünüm hiyerarşisine iç içe yerleştirmenize olanak tanır. Bu iç içe yerleştirme, bir düzen maliyeti de uygulayabilir. Uygulamanız düzen için bir nesne işlediğinde uygulama, düzenin tüm alt öğelerinde de aynı işlemi gerçekleştirir.
Karmaşık bir düzende, bazen yalnızca sistem düzeni ilk kez hesapladığında bir maliyet oluşur. Örneğin, uygulamanız karmaşık bir liste öğesini bir RecyclerView
nesnesinde geri dönüştürdüğünde, sistemin tüm nesneleri düzenlemesi gerekir. Başka bir örnekte, önemsiz değişiklikler, üst öğenin boyutunu etkilemeyen bir nesneye ulaşana kadar zinciri üst öğeye doğru yayabilir.
Düzenin uzun sürmesinin yaygın bir nedeni, View
nesne hiyerarşilerinin iç içe yerleştirilmesidir. İç içe yerleştirilmiş her düzen nesnesi, düzen aşamasının maliyetini artırır. Hiyerarşiniz ne kadar düz olursa düzen aşamasının tamamlanması o kadar kısa sürer.
Genellikle hem daha verimli olduğu hem de düzenlerin iç içe yerleştirilmesini azalttığı için, RelativeLayout
veya LinearLayout
yerine bir ConstraintLayout
oluşturmak için Düzen Düzenleyici'yi kullanmanızı öneririz. Bununla birlikte, FrameLayout
kullanılarak yapılabilecek basit düzenler için FrameLayout
kullanmanızı öneririz.
RelativeLayout
sınıfını kullanıyorsanız bunun yerine iç içe yerleştirilmiş, ağırlıksız LinearLayout
görünümlerini kullanarak aynı etkiyi daha düşük maliyetle elde edebilirsiniz. Bununla birlikte, iç içe yerleştirilmiş, ağırlıklı LinearLayout
görünümleri kullanıyorsanız düzen maliyeti, sonraki bölümde açıklandığı gibi birden fazla düzen geçişi gerektirdiğinden çok daha yüksek olur.
Ayrıca, liste öğelerinin ayrı ayrı düzenlerini geri dönüştürebileceği ve bu şekilde hem daha verimli hem de kaydırma performansını iyileştirebileceği için ListView
yerine RecyclerView
kullanmanızı öneririz.
Çifte vergilendirme
Tipik olarak çerçeve, düzeni veya ölçüm aşamasını tek bir geçişte yürütür. Bununla birlikte, bazı karmaşık düzen durumlarında çerçevenin, öğeleri konumlandırmadan önce hiyerarşinin birden çok geçiş gerektiren bölümlerinde birkaç kez iterasyon yapması gerekebilir. Birden fazla düzen ve ölçüm yinelemesi uygulanmasına çift vergi denir.
Örneğin, View
nesnelerini diğer View
nesnelerinin konumlarına göre konumlandırmanıza olanak tanıyan RelativeLayout
kapsayıcısını kullandığınızda çerçeve aşağıdaki sırayı gerçekleştirir:
- Düzen ve ölçüm geçişi yürütülür. Bu geçiş sırasında çerçeve, her alt nesnenin isteğine göre her alt nesnenin konumunu ve boyutunu hesaplar.
- İlişkili görünümlerin doğru konumunu belirlemek için bu verileri nesne ağırlıklarını dikkate alarak kullanır.
- Nesnelerin konumlarını sonlandırmak için ikinci bir düzen geçişi gerçekleştirir.
- Oluşturma işleminin bir sonraki aşamasına geçer.
Görünüm hiyerarşinizde ne kadar fazla düzey bulunursa performans cezası olasılığı o kadar artar.
Daha önce belirtildiği gibi ConstraintLayout
, genellikle FrameLayout
dışındaki düzenlerden daha verimlidir. Birden fazla düzen geçişine daha az eğilimlidir ve birçok durumda düzenleri iç içe yerleştirme ihtiyacını ortadan kaldırır.
RelativeLayout
dışındaki kapsayıcılar da çift vergilendirmeyi artırabilir. Örneğin:
LinearLayout
görünümünü yatay yaparsanız iki kez düzen ve ölçüm geçişi yapılabilir.measureWithLargestChild
eklerseniz dikey yönde de çift düzen ve ölçüm geçişi gerçekleşebilir. Bu durumda, çerçevenin uygun boyutlardaki nesneleri çözümlemek için ikinci bir geçiş yapması gerekebilir.GridLayout
, göreli konumlandırmaya da izin verir ancak normalde alt görüntülemeler arasındaki konum ilişkilerinin önceden işlenmesiyle çifte vergilendirmeyi önler. Bununla birlikte, düzen ağırlıkları kullanıyorsa veyaGravity
sınıfıyla dolduruyorsa ön işlemenin avantajı kaybolur ve kapsayıcıRelativeLayout
ise çerçevenin birden fazla geçiş yapması gerekebilir.
Birden fazla düzen ve ölçüm geçişi, performans yükü anlamına gelmez. Ama yanlış yerdeyken yükler oluşturabilirler. Kapsayıcınız için aşağıdaki koşullardan birinin geçerli olduğu durumlarda dikkatli olun:
- Bu, görünüm hiyerarşinizdeki kök öğedir.
- Altında derin bir görünüm hiyerarşisi vardır.
ListView
nesnesindeki alt öğelere benzer şekilde, ekranı dolduran birçok bunun örneği vardır.
Görünüm hiyerarşisi sorunlarını teşhis etme
Düzen performansı, birçok yönü olan karmaşık bir sorundur. Aşağıdaki araçlar, performans sorunlarının nerede meydana geldiğini belirlemenize yardımcı olabilir. Bazı araçlar daha az kesin bilgi sağlar ama yararlı ipuçları sağlayabilir.
Perfetto
Perfetto, performans hakkında veri sağlayan bir araçtır. Android izlerini Perfetto kullanıcı arayüzünden açabilirsiniz.
Profil GPU oluşturma
Android 6.0 (API düzeyi 23) ve sonraki sürümleri çalıştıran cihazlarda kullanılabilen cihaz üzerinde Profil GPU oluşturma aracı, performanstaki performans sorunları hakkında somut bilgiler sağlayabilir. Bu araç, her oluşturma karesi için düzen ve ölçü aşamasının ne kadar sürdüğünü görmenize olanak tanır. Bu veriler, çalışma zamanı performans sorunlarını teşhis etmenize ve ele almanız gereken düzen ve ölçüm sorunlarını belirlemenize yardımcı olabilir.
Yakaladığı verilerin grafik temsilinde Profil GPU oluşturma, düzen zamanını temsil etmek için mavi rengi kullanır. Bu aracın nasıl kullanılacağı hakkında daha fazla bilgi için Profil GPU oluşturma hızı bölümüne bakın.
Hav
Android Studio'nun Lint aracı, görünüm hiyerarşisindeki verimsizliklerle ilgili bir fikir edinmenize yardımcı olabilir. Bu aracı kullanmak için şekil 1'de gösterildiği gibi Analiz > Kodu İncele'yi seçin.
Android > Lint > Performans bölümünde çeşitli düzen öğeleriyle ilgili bilgiler görünür. Daha fazla ayrıntı görmek için öğeleri tıklayarak genişletin ve ekranın sağ tarafındaki bölmede daha fazla bilgi görüntüleyin. Şekil 2'de genişletilmiş bilgilerin bir örneği gösterilmektedir.
Bir öğeyi tıkladığınızda, sağdaki bölmede bu öğeyle ilişkili sorunlar gösterilir.
Bu alandaki belirli konular ve sorunlar hakkında daha fazla bilgi edinmek için Lint belgelerine bakın.
Düzen Denetleyici
Android Studio'nun Düzen İnceleyici aracı, uygulamanızın görünüm hiyerarşisinin görsel bir temsilini sağlar. Bu özellik, belirli bir görünümün ana zincirinin net bir görsel temsilini sunarak uygulamanızın hiyerarşisinde gezinmenin iyi bir yoludur ve uygulamanızın oluşturduğu düzenleri incelemenize olanak tanır.
Layout Inspector'ın sunduğu görünümler, çift vergilendirmeden kaynaklanan performans sorunlarını belirlemeye de yardımcı olabilir. Ayrıca, iç içe yerleştirilmiş düzenlerin derin zincirlerini veya çok sayıda iç içe yerleştirilmiş alt öğenin bulunduğu düzen alanlarını tanımlamanıza da bir yol sağlayabilir. Bu durum, performans maliyetlerine neden olabilir. Bu gibi durumlarda, düzen ve ölçme aşamaları maliyetli olabilir ve performans sorunlarına yol açabilir.
Daha fazla bilgi için Düzen Denetleyici ve Düzen Doğrulama ile düzeninizde hata ayıklama bölümüne bakın.
Görünüm hiyerarşisi sorunlarını çözme
Görünüm hiyerarşilerinden kaynaklanan performans sorunlarının çözülmesinin ardındaki temel kavram, uygulamada zor olabilir. Görünüm hiyerarşilerinin performans cezaları uygulanmasını önlemek için görünüm hiyerarşinizi düzleştirir ve çifte vergilendirmeyi azaltın. Bu bölümde, bu hedeflere ulaşma stratejileri anlatılmaktadır.
Gereksiz iç içe yerleştirilmiş düzenleri kaldırma
ConstraintLayout
,
görünümleri yerleşim içinde konumlandırmak için çok sayıda farklı mekanizmaya sahip bir Jetpack kitaplığıdır. Bu, bir ConstaintLayout
öğesini iç içe yerleştirme ihtiyacını azaltır ve görünüm hiyerarşisinin düzelmesine yardımcı olabilir. ConstraintLayout
kullanılarak hiyerarşileri birleştirmek, diğer düzen türleriyle karşılaştırıldığında genellikle daha basittir.
Geliştiriciler genellikle gereğinden fazla iç içe yerleştirilmiş düzenler kullanır. Örneğin, bir RelativeLayout
kapsayıcısı, aynı zamanda bir RelativeLayout
kapsayıcısı olan tek bir alt öğe içerebilir. Bu iç içe yerleştirme gereksizdir ve görünüm hiyerarşisine gereksiz maliyet ekler. Lint, bu sorunu sizin yerinize işaretleyerek hata ayıklama süresini kısaltabilir.
Birleştirme veya dahil et
Gereksiz iç içe yerleştirilmiş düzenlerin sık karşılaşılan bir nedeni <include>
etiketidir. Örneğin, aşağıdaki gibi yeniden kullanılabilir bir düzen tanımlayabilirsiniz:
<LinearLayout> <!-- some stuff here --> </LinearLayout>
Daha sonra, aşağıdaki öğeyi üst kapsayıcıya eklemek için bir <include>
etiketi ekleyebilirsiniz:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/app_bg" android:gravity="center_horizontal"> <include layout="@layout/titlebar"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/hello" android:padding="10dp" /> ... </LinearLayout>
Önceki düzen, ilk düzeni gereksiz bir şekilde ikinci düzene yerleştiriyor.
<merge>
etiketi bu sorunu önlemeye yardımcı olabilir. Bu etiket hakkında bilgi için <merge> etiketini kullanma bölümünü inceleyin.
Daha ucuz bir düzen kullanın
Mevcut düzen şemanızı gereksiz düzenler içermeyecek şekilde ayarlayamayabilirsiniz. Belirli durumlarda tek çözüm, tamamen farklı bir düzen türüne geçerek hiyerarşinizi düzleştirmek olabilir.
Örneğin, TableLayout
işlevinin, birçok konum bağımlılığı olan daha karmaşık bir düzenle aynı işlevi sunduğunu görebilirsiniz. Jetpack kitaplığı ConstraintLayout
, RelativeLayout
ile benzer işlevler ve daha şık ve etkili düzenler oluşturmaya yardımcı olan daha fazla özellik sunar.