Donanım hızlandırma

Android 3.0 (API düzeyi 11) sürümünden itibaren, Android 2D oluşturma ardışık düzeni donanımı destekler ivme, yani bir test üzerinde gerçekleştirilen tüm çizim işlemleri View adlı kullanıcının kanvası GPU'yu kullanıyor. Bu özelliği etkinleştirmek için gereken kaynakların artması uygulamanız daha fazla RAM kullanır.

Hedef API düzeyiniz >=14 ise donanım hızlandırma varsayılan olarak etkindir. Ancak bunu etkinleştirilmelidir. Uygulamanız yalnızca standart görünümler ve Drawable durumunda ise bu özelliğin genel olarak etkinleştirilmesi ters çizime neden olmaz. hoşuma gidiyor. Ancak tüm 2D çizimlerde donanım hızlandırma desteklenmediğinden işlemleri için etkinleştirildiğinde, özel görünümlerinizden veya çizim çağrılarınızdan bazılarını etkileyebilir. Sorunlar kendilerini genellikle görünmez öğeler, istisnalar veya yanlış oluşturulmuş pikseller olarak gösterir. Alıcı: telafi etmek için, Android size donanım hızlandırmayı birden fazla cihazda etkinleştirme veya devre dışı bırakma seviyelere dokunun. Donanım hızlandırmayı denetleme başlıklı makaleyi inceleyin.

Uygulamanız özel çizim yapıyorsa uygulamanızı gerçek donanım cihazlarında test edin bulun. Çizim işlemleri için destek bölümünde, donanım hızlandırma ve bunların nasıl çözüleceği.

Ayrıca Çerçeve API'leriyle OpenGL başlıklı makaleyi de inceleyin ve Renderscript

Donanım hızlandırmayı denetleme

Donanım hızlandırmayı aşağıdaki düzeylerde denetleyebilirsiniz:

  • Başvuru
  • Etkinlik
  • Pencere
  • Göster

Uygulama düzeyi

Android manifest dosyanızda, aşağıdaki özelliği Tüm cihazınız için donanım hızlandırmayı etkinleştirmek üzere <application> uygulama:

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

Etkinlik düzeyi

Genel olarak donanım hızlandırma etkinken uygulamanız düzgün çalışmıyorsa bu seçeneği, bireysel etkinlikler için de kontrol edebiliyorsunuz. Şu adresten donanım hızlandırmayı etkinleştirmek veya devre dışı bırakmak için: kullanıyorsanız android:hardwareAccelerated özelliğini kullanarak <activity> öğesi. Aşağıdaki örnekte, mobil cihazlar için donanım hızlandırmayı uygulamanın tamamını ancak bir etkinlik için devre dışı bırakırsa:

<application android:hardwareAccelerated="true">
    <activity ... />
    <activity android:hardwareAccelerated="false" />
</application>

Pencere düzeyi

Daha da hassas denetime ihtiyacınız olursa belirli bir alan için donanım hızlandırmayı penceresinde bulunur:

Kotlin

window.setFlags(
        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
)

Java

getWindow().setFlags(
    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
    WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);

Not: Şu anda donanım hızlandırmayı pencere seviyesinde

Görünüm düzeyi

Çalışma zamanında tek bir görünüm için donanım hızlandırmayı şu kodu kullanabilirsiniz:

Kotlin

myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null)

Java

myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

Not: Şu anda aşağıdaki adresten donanım hızlandırmayı etkinleştiremezsiniz: görünüm düzeyiyle belirlenir. Görünüm katmanlarının, donanım hızlandırmayı devre dışı bırakma dışında başka işlevleri de vardır. Kullanımları hakkında daha fazla bilgi için Katmanları görüntüleme konusuna bakın.

Bir görünümün donanım hızlandırmalı olup olmadığını belirleme

Bazen bir uygulamanın, şu anda donanım üzerinde çalışan özellikle de özel görünümler gibi metrikler için hızlandırılmıştır. Bu, özellikle çok sayıda özel çizim yaptığından, yeni çizim uygulaması tarafından yapılan tüm işlemler ardışık düzeni oluşturur.

Uygulamanın donanım hızlandırmalı olup olmadığını kontrol etmenin iki farklı yolu vardır:

Bu kontrolü çizim kodunuzda yapmanız gerekiyorsa Bunun yerine Canvas.isHardwareAccelerated() Mümkün olduğunda View.isHardwareAccelerated(). Bir görüntüleme bir donanım hızlandırmalı pencereye bağlandığında, yine de donanım olmayan bir pencere kullanılarak çizilebilir. hızlandırılmış Canvas. Bu durum, örneğin, önbelleğe alma için bir bit eşlem üzerinde görünüm çizerken yaşanır amaçlar.

Android çizim modelleri

Donanım hızlandırma etkinleştirildiğinde Android çerçevesi farklı bir çizim modeli kullanır. uygulamanızı ekranda oluşturmak için görüntüleme listelerini kullanır. Tam olarak anlamak için uygulamanızı nasıl etkileyebileceğini öğrendiğinize göre, Android'in donanım hızlandırma olmadan da görünümler çizer. Aşağıdaki bölümlerde, yazılım tabanlı ve donanım hızlandırmalı çizim modelleridir.

Yazılım tabanlı çizim modeli

Yazılım çizim modelinde görünümler aşağıdaki iki adımla çizilir:

  1. Hiyerarşiyi geçersiz kıl
  2. Hiyerarşiyi çizme

Bir uygulamanın, kullanıcı arayüzünün bir bölümünü güncellemesi gerektiğinde, değişen herhangi bir görünümde invalidate() yöntemini (veya varyantlarından birini) çağırır içerik. Geçersiz kılma mesajları, hesaplama işlemi için görünüm hiyerarşisinin en üstüne ekranın yeniden çizilmesi gereken bölgelerine (kirli bölge) girin. Ardından Android sistemi, hiyerarşide kirli bölgeyle kesişen herhangi bir görünüm çizer. Maalesef iki dezavantajı vardır:

  • Öncelikle, bu model her çizim işleminde çok fazla kod yürütmeyi gerektirir. Örneğin, uygulamanız bir düğmede invalidate() çağırıyor ve düğmesi başka bir görünümün üstünde duruyorsa, Android sistemi değiştirildi.
  • İkinci sorun, çizim modelinin uygulamanızdaki hataları gizleyebilmesidir. Android sistemi, kirli bölgeyle kesişen görüntülemeleri yeniden çizer. invalidate() değiştirilmemiş olsa bile değiştirilmiş olanlar yeniden çizilebilir karar verdim. Bu durumda, ikinci bir görünüm elde etmek için başka bir görünümün geçersiz doğru davranışa yol açabilir. Bu davranış, uygulamanızda her değişiklik yaptığınızda değişebilir. Bunun nedeni: Özel üzerinde her zaman invalidate() ile iletişime geçmelisiniz. görüntüleyebilirsiniz.

Not: Android görünümlerinde (ör. arka plan) özellikleri değiştiğinde invalidate() otomatik olarak çağrılacaktır TextView içindeki metni seçin.

Donanım hızlandırmalı çizim modeli

Android sistemi, ekran güncellemesi istemek ve görünüm oluşturmak için invalidate() ve draw() kullanmaya devam eder, ancak farklı olabilir. Çizim komutlarını hemen yürütmek yerine, Android sistem, bunları görünüm hiyerarşisinin çıkışını içeren görüntü listelerine kaydeder. anlamına gelir. Diğer bir optimizasyon da Android sisteminin yalnızca kayıt ve güncelleme yapmasıdır. invalidate() ile kirli olarak işaretlenen görüntülemelerin listelerini gösterir çağrısına bir tıklama URL'si eklemeniz gerekir. Geçersiz kılınmamış görünümler, daha önce yeniden çizilerek yeniden çizilebilir. kaydedilen ekran gösterilir. Yeni çizim modeli üç aşamadan oluşur:

  1. Hiyerarşiyi geçersiz kıl
  2. Görüntü listelerini kaydetme ve güncelleme
  3. Ekran listelerini çizin

Bu modelde, draw() yönteminin yürütülmesi için kirli bölgeyle kesişen bir görünümden yararlanamazsınız. Android sisteminin bir görünümünün görüntüleme listesindeyse invalidate() yöntemini çağırmanız gerekir. Unutma bunu yapmak, görünümün değiştirildikten sonra bile aynı görünmesine neden olur.

Görüntüleme listelerini kullanmak animasyon performansının da faydasını sağlar çünkü belirli özellikler ayarlanır, Örneğin, alfa veya rotasyon gibi, hedeflenen görünümün geçersiz kılınmasını gerektirmez ( otomatik olarak) sağlar. Bu optimizasyon, görüntüleme listesi içeren görünümler için de (reklamlarınızın için hızlandırılmıştır.) Örneğin, Button değerinin üzerinde ListView içeren bir LinearLayout olduğunu varsayalım. LinearLayout için görüntüleme listesi şöyle görünüyor bu:

  • DrawDisplayList(ListView)
  • DrawDisplayList(Düğme)

Şimdi ListView öğesinin opaklığını değiştirmek istediğinizi varsayalım. Şu tarihten sonra: ListView cihazında setAlpha(0.5f) çağrılıyor, görüntüleme listesi şimdi gösteriliyor şunu içerir:

  • SaveKatmanAlpha(0,5)
  • DrawDisplayList(ListView)
  • Geri yükle
  • DrawDisplayList(Düğme)

ListView öğesinin karmaşık çizim kodu yürütülmedi. Bunun yerine sistem yalnızca çok daha basit olan LinearLayout öğelerinin görüntüleme listesini güncelledi. İçinde etkinleştirilmiş olmayan bir uygulama için, hem listenin hem de tekrar yürütülür.

Çizim işlemleri desteği

Donanım hızlandığında, 2D oluşturma ardışık düzeni en yaygın olarak kullanılan Canvas çizim işlemlerinin yanı sıra daha az kullanılan çok sayıda işlem. Tüm Android ile birlikte gelen uygulamaları oluşturmak için kullanılan çizim işlemleri, varsayılan widget'lar ve yansıma ve karolara ayrılmış dokular gibi yaygın olarak kullanılan gelişmiş görsel efektler, desteklenir.

Aşağıdaki tabloda, API düzeylerinde çeşitli işlemlerin destek düzeyi açıklanmaktadır:

Desteklenen ilk API düzeyi
Tuval
PaintBitmapMesh() (renk dizisi) 18
PaintPicture() 23
drawPosText() 16
PaintTextOnPath() 16
drawVertices() 29
setDrawFilter() 16
klipYolu() 18
klipBölge() 18
klipRect(Bölge.Op.XOR) 18
klipRect(Bölge.Op.Farkı) 18
klipRect(Bölge.Op.Tersine Fark) 18
Döndürme/perspektif ile klipRect() 18
Boyama yapın
setAntiAlias() (metin için) 18
setAntiAlias() (satırlar için) 16
setFilterBitmap() 17
setDoğrusalText()
setMaskFilter()
setPathEffect() (satırlar için) 28
setShadowKatman() (metin dışında) 28
setStrokeCap() (satırlar için) 18
setStrokeCap() (puanlar için) 19
setSubpixelText() 28
Xfermode
PorterDuff.Mode.DARKEN (çerçeve arabelleği) 28
PorterDuff.Mode.LIGHTEN (framebuffer) 28
PorterDuff.Mode.OVERLAY (çerçeve arabelleği) 28
Gölgelendirici
ComposeShader'daki ComposeShader'ı 28
ComposeShader içinde aynı tür gölgelendiriciler 28
ComposeShader'daki yerel matris 18

Tuval ölçeklendirme

Donanım hızlandırmalı 2D oluşturma ardışık düzeni, öncelikle ölçeklendirilmemiş çizimi desteklemek için derlenmiştir. Bazı çizim işlemleri daha yüksek ölçek değerlerinde kaliteyi önemli ölçüde düşürüyor. Bu işlemleri, 1.0 ölçeğinde çizilen ve GPU tarafından dönüştürülen dokular şeklinde uygulanır. API'de başlatılıyor tüm çizim işlemleri sorunsuz şekilde ölçeklenebilir.

Aşağıdaki tabloda, uygulamanın büyük ölçekleri doğru şekilde işlemek için ne zaman değiştirildiği gösterilmektedir:
Ölçeklendirilecek çizim işlemi Desteklenen ilk API düzeyi
PaintText() 18
drawPosText() 28
PaintTextOnPath() 28
Basit Şekiller* 17
Karmaşık Şekiller* 28
PaintPath() 28
Gölge katmanı 28

Not: "Basit" şekiller drawRect(), drawCircle(), drawOval(), drawRoundRect() ve drawArc() (useCenter=false ile) içermeyen bir Boya ile yayınlanan komutlar PathEffect'tir ve varsayılan olmayan birleştirmeler içermez (setStrokeJoin() / setStrokeMiter()) seçin. Bu çizim komutlarının diğer örnekleri "Karmaşık" inç yukarıdaki tabloya bakın.

Uygulamanız bu eksik özelliklerden veya sınırlamalardan herhangi birinden etkileniyorsa uygulamanızın yalnızca etkilenen bölümü için donanım hızlandırmasını setLayerType(View.LAYER_TYPE_SOFTWARE, null) Bu sayede projenizin diğer her yerde donanım hızlandırmadan yararlanmaya devam edebilirsiniz. Etkinleştirme hakkında daha fazla bilgi için Donanım hızlandırmayı denetleme başlıklı makaleye bakın. ve uygulamanızda farklı düzeylerde donanım hızlandırmayı devre dışı bırakın.

Katmanları görüntüleme

Android'in tüm sürümlerinde, görünümler ekran dışı arabelleklerde oluşturulabiliyordu. veya Canvas.saveLayer() kullanarak bir görünümün çizim önbelleğini kullanabilirsiniz. Ekran dışındaki arabelleklerin veya katmanların çeşitli kullanım alanları vardır. Bu araçları ekiple paylaşılan daha iyi performans elde edebilir. Örneğin, Bir görünümü geçici olarak oluşturmak için Canvas.saveLayer() kullanarak solma efektlerini uygulayabilirsiniz sonra bir opaklık faktörüyle tekrar ekranda birleştiriyoruz.

Android 3.0 (API düzeyi 11) sürümünden itibaren, katmanların nasıl ve ne zaman kullanılacağı konusunda daha fazla kontrole sahip olursunuz. View.setLayerType() yöntemiyle deneyin. Bu API iki parametreler: kullanmak istediğiniz katmanın türü ve isteğe bağlı Paint katmanın nasıl birleştirilmesi gerektiğini açıklayan nesnedir. Bir öğeye renk filtreleri, özel karıştırma modları veya opaklık uygulamak için Paint parametresini kullanabilirsiniz. katmanıdır. Bir görünümde üç katman türünden biri kullanılabilir:

  • LAYER_TYPE_NONE: Görünüm normal şekilde oluşturulur ve desteklenmez ekran dışı bir arabellek tarafından yapılır. Bu, varsayılan davranıştır.
  • LAYER_TYPE_HARDWARE: Görünüm, donanımda aşağıdaki gibi oluşturulur: uygulama, donanım hızlandırmalıysa donanım dokusunu kullanır. Uygulama, donanım değilse bu katman türü LAYER_TYPE_SOFTWARE ile aynı şekilde davranır.
  • LAYER_TYPE_SOFTWARE: Görünüm, yazılım biçiminde bit eşlem.

Kullandığınız katmanın türü hedefinize bağlıdır:

  • Performans: Görünümü donanıma dönüştürmek için donanım katmanı türü kullanın dokunun. Bir görünüm bir katmana dönüştürüldükten sonra, çizim kodunun yürütülmesi gerekmez görünüm invalidate() çağırana kadar. Örneğin, Böylece, alfa animasyonları doğrudan katmana uygulanabilir. tam ekran görüntüsü olduğunu hissediyorum.
  • Görsel efektler: Görünümlere özel görsel işlemler uygulamak için bir donanım veya yazılım katmanı türü ve Paint kullanın. Örneğin herkesin ColorMatrixColorFilter kullanarak siyah beyaz bir görünüm çizin.
  • Uyumluluk: Bir görünümün oluşturulmasını zorunlu kılmak için yazılım katmanı türü kullanın daha fazla bilgi edineceksiniz. Donanım hızlandırmalı bir görünüm (örneğin, donanım hızlandırmalıysa), oluşturma sorunları yaşıyorsa bu, çalışmanın kolay bir yoludur sorunları çözmek için ardışık düzendir.

Katmanları ve animasyonları görüntüleme

Donanım katmanları, uygulamanız sırasında daha hızlı ve daha akıcı animasyonlar sunabilir donanım hızlandırmalı bir yöntemdir. Saniyede 60 kare hızında bir animasyon çalıştırmak çok sayıda çizim işlemi yapan karmaşık görünümlere animasyon oluşturmaktır. Bu durum, hedef kitlenize nasıl görünümü donanım dokusuna dönüştürmek için donanım katmanlarını kullanma. Donanım dokusu, daha sonra görünümü canlandırmak için kullanılır. Böylece, görünümün kendini sürekli olarak yeniden çizme ihtiyacını ortadan kaldırır. dikkat edin. Görünümü değiştirmediğiniz sürece görünüm yeniden çizilmez özelliklerini (invalidate()) çağıran ya da invalidate() öğesini manuel olarak çağıran özellikler. İçinde bir animasyon çalıştırdığınızda ve istediğiniz sorunsuz sonuçları alamazsanız, şurada donanım katmanlarını etkinleştirmeyi düşünün: elde edebilirsiniz.

Bir görünüm bir donanım katmanı tarafından desteklendiğinde, bazı özellikleri katman ekranda birleştirilir. Bu özellikleri ayarlamak, görünümün geçersiz kılınmasını ve yeniden çizilmesini gerektirir. Aşağıdaki özellik listesi, katman birleştirilir. Bu özelliklerden herhangi biri için belirleyicinin çağrılması, Hedeflenen görünümü geçersiz kılma ve yeniden çizilmemesi:

  • alpha: Katmanın opaklığını değiştirir
  • x, y, translationX, translationY: Katmanın konumunu değiştirir
  • scaleX, scaleY: Katmanın boyutunu değiştirir
  • rotation, rotationX, rotationY: katmanın 3D uzaydaki yönü
  • pivotX, pivotY: Katmanın dönüşüm kaynağını değiştirir

Bu özellikler, ObjectAnimator ile bir görünüm canlandırırken kullanılan adlardır. Bu mülklere erişmek istiyorsanız belirleyicidir. Örneğin, alfa özelliğini değiştirmek için setAlpha() yöntemini çağırın. Aşağıdaki kod snippet'i, en verimli şekilde bir görünümü Y ekseni etrafında 3D olarak döndürmek için:

Kotlin

view.setLayerType(View.LAYER_TYPE_HARDWARE, null)
ObjectAnimator.ofFloat(view, "rotationY", 180f).start()

Java

view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
ObjectAnimator.ofFloat(view, "rotationY", 180).start();

Donanım katmanları video belleği kullandığı için bunları etkinleştirmeniz önemle tavsiye edilir. yalnızca animasyon süresi boyunca kullanabilir ve animasyon bittikten sonra bunları devre dışı bırakabilirsiniz. Siz animasyon işleyicileri kullanarak bunu yapabilirsiniz:

Kotlin

view.setLayerType(View.LAYER_TYPE_HARDWARE, null)
ObjectAnimator.ofFloat(view, "rotationY", 180f).apply {
    addListener(object : AnimatorListenerAdapter() {
        override fun onAnimationEnd(animation: Animator) {
            view.setLayerType(View.LAYER_TYPE_NONE, null)
        }
    })
    start()
}

Java

view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "rotationY", 180);
animator.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
        view.setLayerType(View.LAYER_TYPE_NONE, null);
    }
});
animator.start();

Mülk animasyonu hakkında daha fazla bilgi için Mülk animasyonu konusuna bakın.

İpuçları ve püf noktaları

Donanım hızlandırmalı 2D grafiğe geçmek performansı anında artırabilir, ancak yine de aşağıdaki adımları izleyerek uygulamanızı GPU'yu etkili bir şekilde kullanacak şekilde tasarlamanız gerekir: öneriler:

Uygulamanızdaki görüntüleme sayısını azaltma
Sistemin görüntüleme sayısı ne kadar fazlaysa sistem de o kadar yavaş olacaktır. Bu, yazılımın ardışık düzeni oluşturabilirsiniz. Görüntüleme sayısını azaltmak, kullanıcı arayüzünüzü optimize etmenin en kolay yollarından biridir.
Fazla çizimden kaçınma
Birbirinin üzerine çok fazla katman çizmeyin. Kaybolan tüm görünümleri yarı saydam görünümlerle örtüler. Üste karıştırılmış birkaç katman çizmeniz gerekiyorsa bunları tek bir katmanda birleştirmeyi düşünün. Mevcut iş ortağı ile ilgili ekranda kare başına piksel sayısının 2,5 katından fazla çizim yapmaması gerekir (bir bit eşlem sayısındaki şeffaf pikseller!).
Çizim yöntemlerinde oluşturma nesneleri oluşturma
Bir oluşturma yöntemi her çağrıldığında yeni bir Paint veya yeni bir Path oluşturmak, sık yapılan bir hatadır. Bu da çöpe atılan daha sık çalışmasını ve donanımdaki önbellekleri ve optimizasyonları atlar ardışık düzendir.
Şekilleri çok sık değiştirmeyin
Örneğin karmaşık şekiller, yollar ve daireler, doku maskeleri kullanılarak oluşturulur. Hepsini Bir yol oluşturduğunuzda veya değiştirdiğinizde donanım ardışık düzeni, Pahalı.
Bit eşlemleri çok sık değiştirmeyin
Bir bit eşlemin içeriğini her değiştirdiğinizde, bit eşlemin GPU dokusu olarak tekrar yüklenir. bir dahaki sefere çizin.
Alfa sürümünü dikkatli kullanın
setAlpha() kullanarak bir görünümü yarı saydam yaptığınızda, AlphaAnimation veya ObjectAnimator, o değeri, gerekli doluluk oranını iki katına çıkaran bir ekran dışı arabellekte oluşturulur. Alfa uygulanırken çok büyük görünümlerde, görünümün katman türünü LAYER_TYPE_HARDWARE