JankStats Kitaplığı

JankStats kitaplığı hesabınızdaki performans sorunlarını izleyip analiz etmenize izin verir. Jank, oluşturulması çok uzun süren uygulama çerçeveleri ve JankStats kitaplığı da uygulamanızın olumsuzluk istatistikleriyle ilgili raporlar sunar.

İşlemler

JankStats, aşağıdakiler de dahil olmak üzere mevcut Android platformu özelliklerini temel alarak geliştirildi FrameMetrics API Android 7 (API düzeyi 24) ve sonraki sürümlerde veya önceki sürümlerde OnPreDrawListener'da sürümleri vardır. Bu mekanizmalar, uygulamaların, karelerin ne kadar sürdüğünü belirir. JanksStats kitaplığını oluşturan iki ek özellik vardır: daha dinamik ve kullanımı daha kolay: jank bulguları ve kullanıcı arayüzü durumu.

Jank buluşsal yöntemler

Kare sürelerini izlemek için FrameMetrics'i kullanabilirsiniz, ancak FrameMetrics oluşabilecek olumsuzluğun belirlenmesine yardımcı olmayı teklif eder. Ancak JankStats'ın aksatmanın ne zaman gerçekleştiğini belirlemek için yapılandırılabilir, dahili mekanizmalar yararlı hale getirir.

Kullanıcı arayüzü durumu

Genellikle uygulamanızdaki performans sorunlarının bağlamını bilmeniz gerekir. Örneğin, FrameMetrics kullanan karmaşık, birden çok ekranlı bir uygulama geliştirirseniz ve uygulamanızda genelde son derece hantal çerçeveler olduğunu fark ederseniz sorunun nerede, ne olduğunu ve sorunun ne olduğunu öğrenerek ve bunu tekrarlamanın yolları arasındadır.

JankStats, aşağıdakileri yapmanıza olanak tanıyan bir state API'si sunarak bu sorunu çözer: kitaplıkla iletişim kurarak uygulama Etkinliği hakkında bilgi sağlar. Zaman JankStats, düzgün çalışmayan bir çerçeveyle ilgili bilgileri günlüğe kaydeder. neden olabilir.

Kullanım

JankStats'ı kullanmaya başlamak için her örnek için kitaplığı örneklendirin ve etkinleştirin Window. Her JankStats nesnesi verileri izler yalnızca Window içinde olması gerekir. Kitaplığı örneklendirmek için Window örneği gerekir bir OnFrameListener ile birlikte işleyiciyi ifade eder. Her ikisi de metrikleri müşteriye göndermek için kullanılır. Dinleyiciye çağrıda bulunan: Her karede FrameData ve şu konular hakkında ayrıntılı bilgi verir:

  • Kare başlangıç zamanı
  • Süre değerleri
  • Çerçevenin olumsuzluk olarak kabul edilip edilmeyeceği
  • Uygulama durumu hakkında bilgiler içeren bir dizi Dize çifti kare sırasında

JankStats'ı daha faydalı hale getirmek için uygulamaların kitaplığı FrameData'daki raporlama için alakalı kullanıcı arayüzü durum bilgilerini içerir. Şunları yapabilirsiniz: aracılığıyla PerformanceMetricsState Tüm durum yönetimi mantığının ve API'lerin sunulduğu API (doğrudan JankStats değil) canlı yayınlar.

Başlatma

JankStats kitaplığını kullanmaya başlamak için önce Gradle dosyası:

implementation "androidx.metrics:metrics-performance:1.0.0-beta01"

Daha sonra, her bir Window için JankStats'ı başlatın ve etkinleştirin. Şunu da duraklatmalısınız: JankStats, bir Etkinlik arka planda olduğunda izleme yapıyor. Oluştur ve etkinleştir Etkinlik geçersiz kılma işlemlerinizdeki JankStats nesnesi:

class JankLoggingActivity : AppCompatActivity() {

    private lateinit var jankStats: JankStats


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ...
        // metrics state holder can be retrieved regardless of JankStats initialization
        val metricsStateHolder = PerformanceMetricsState.getHolderForHierarchy(binding.root)

        // initialize JankStats for current window
        jankStats = JankStats.createAndTrack(window, jankFrameListener)

        // add activity name as state
        metricsStateHolder.state?.putState("Activity", javaClass.simpleName)
        // ...
    }

Yukarıdaki örnek, mevcut JankStats nesnesini oluşturduktan sonraki etkinlik. Gelecekteki tüm FrameData raporları bu JankStats nesnesi için oluşturulduğunda artık Etkinlik bilgileri de yer alıyor.

JankStats.createAndTrack yöntemi, bir Window referansı alır nesnesidir. Bu, söz konusu Window içindeki Görünüm hiyerarşisi için bir proxy'dir ve Window için. jankFrameListener, kullanılan iş parçacığında çağrıldı bu bilgileri platformdan JankStats'a dahili olarak iletmek için çalışıyor.

Herhangi bir JankStats nesnesinde izleme ve raporlamayı etkinleştirmek için isTrackingEnabled = true numaralı telefonu arayın. Varsayılan olarak etkin olsa da Bir etkinliğin duraklatılması izlemeyi devre dışı bırakır. Bu durumda, yeniden etkinleştirme işlemini izlemelisiniz. Takibi durdurmak için isTrackingEnabled = false numaralı telefonu arayın.

override fun onResume() {
    super.onResume()
    jankStats.isTrackingEnabled = true
}

override fun onPause() {
    super.onPause()
    jankStats.isTrackingEnabled = false
}

Raporlama

JankStats kitaplığı her kare için tüm veri izlemenizi OnFrameListener tek bir fonksiyondur. Uygulamalar bu verileri depolayıp toplayabilir daha sonra yüklemek üzere verileri içerebilir. Daha fazla bilgi için Toplama bölümünde verilen örneklere göz atın.

Uygulamanızın alması için OnFrameListener oluşturup sağlamanız gerekir çerçeve oluşturmak. Bu dinleyici, her karede sürekli olarak .

private val jankFrameListener = JankStats.OnFrameListener { frameData ->
    // A real app could do something more interesting, like writing the info to local storage and later on report it.
    Log.v("JankStatsSample", frameData.toString())
}

Dinleyici, FrameData nesnesini tanımlayın. Bu istenen çerçeveyle ilgili şu bilgileri içerir:

  • isjank: Çerçevede olumsuzluk yaşanıp yaşanmadığını gösteren bir boole işareti.
  • frameDurationUiNanos: Karenin süresi (nanosaniye cinsinden).
  • frameStartNanos: Çerçevenin başladığı zaman (nanosaniye cinsinden).
  • states: Kare sırasında uygulamanızın durumu.

Android 12 (API düzeyi 31) veya sonraki bir sürümü kullanıyorsanız şunları yapabilirsiniz: kare süreleriyle ilgili daha fazla veri açığa çıkarmak için aşağıdakileri kullanın:

StateInfo hizmetini kullan dinlemesine olanak tanıması gerekir.

OnFrameListener öğesinin, dahili olarak kullanılan ileti dizisinde çağrıldığını unutmayın. çerçeve başına bilgileri JankStats'a iletmektir. Android sürüm 6 (API düzeyi 23) ve önceki sürümlerde bu, Ana (UI) iş parçacığıdır. Android sürüm 7 (API düzeyi 24) ve sonraki sürümlerde iş parçacığı (FrameMetrics için oluşturuldu ve FrameMetrics tarafından kullanılıyor). Her iki durumda da, hızlı bir şekilde geri arama yapabilir ve görebilirsiniz.

Ayrıca, geri çağırmada gönderilen FrameData nesnesinin çerçevesini kullanarak veri raporlaması için yeni nesneler ayırma zorunu ortadan kaldırın. Bunun anlamı şudur: bu nesnenin ne olması gerektiği için bu verileri başka bir yere kopyalayıp geri çağırma işlevi döndürülür.

Toplanıyor

Uygulama kodunuzun kare başına verileri birleştirmesini istersiniz. Bu da bilgileri kendiniz kaydedebilir ve yükleyebilirsiniz. Her ne kadar ayrıntılı kaydetme ve yükleme ile ilgili konular alfa JankStats API'nin kapsamı dışındadır. kare başına verilerin toplanmasıyla ilgili ön Etkinlik'i görüntüleyebilirsiniz. JankAggregatorActivity kullanarak daha geniş bir koleksiyona GitHub deposu.

JankAggregatorActivity kendi raporlamasını katmanlandırmak için JankStatsAggregator sınıfını kullanır sağlamak için JankStats OnFrameListener mekanizmasının en üst kısmındaki yalnızca anlamanızı sağlayacak olan bilgi koleksiyonunu pek çok çerçeveyi kapsıyor.

Doğrudan JankStats nesnesi oluşturmak yerine JankAggregatorActivity bir JankStatsAggregator oluşturur nesnesini ifade eder:

class JankAggregatorActivity : AppCompatActivity() {

    private lateinit var jankStatsAggregator: JankStatsAggregator


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ...
        // Metrics state holder can be retrieved regardless of JankStats initialization.
        val metricsStateHolder = PerformanceMetricsState.getHolderForHierarchy(binding.root)

        // Initialize JankStats with an aggregator for the current window.
        jankStatsAggregator = JankStatsAggregator(window, jankReportListener)

        // Add the Activity name as state.
        metricsStateHolder.state?.putState("Activity", javaClass.simpleName)
    }

JankAggregatorActivity uygulamasında duraklatmak ve takibi devam ettirmek için bir sinyal olarak pause() etkinliğini ekleyerek yaşam döngüsü değişiklikleri bir rapor gibi göründüğünden, issueJankReport() çağrısı içeren bir rapor uygulamadaki olumsuzluk durumunu yakalamak için uygun bir zaman belirleyin:

override fun onResume() {
    super.onResume()
    jankStatsAggregator.jankStats.isTrackingEnabled = true
}

override fun onPause() {
    super.onPause()
    // Before disabling tracking, issue the report with (optionally) specified reason.
    jankStatsAggregator.issueJankReport("Activity paused")
    jankStatsAggregator.jankStats.isTrackingEnabled = false
}

Yukarıdaki örnek kod, bir uygulamanın JankStats'ı etkinleştirmesi ve çerçeve verileri.

Eyaleti yönetme

JankStats'ı özelleştirmek için diğer API'leri çağırmak isteyebilirsiniz. Örneğin, uygulama durumu bilgilerinin eklenmesi, çerçeve verilerini şu şekilde daha yararlı hale getirir: aksamaya yol açan çerçeveler için bağlam sağlar.

Bu statik yöntem, MetricsStateHolder nesnesini ifade eder.

PerformanceMetricsState.getHolderForHierarchy(view: View): MetricsStateHolder

Etkin bir hiyerarşideki herhangi bir görünüm kullanılabilir. Dahili olarak bu, onunla ilişkilendirilmiş mevcut bir Holder nesnesi olup olmadığı görebilirsiniz. Bu bilgiler, sayfanın en üstündeki görünümde önbelleğe alınır hiyerarşik olarak düzenlenmiştir. Böyle bir nesne yoksa getHolderForHierarchy() bir tane oluşturur.

Statik getHolderForHierarchy() yöntemi, önbelleğe alma zorunluluğunu ortadan kaldırır. sahip örneğini daha sonra almak üzere bir yere alır ve kodda herhangi bir yerde bulunan mevcut bir durum nesnesini (hatta kitaplık kodunda aksi takdirde orijinal örneğe erişemez).

Döndürülen değerin, durum nesnesinin kendisi değil, bir tutucu nesne olduğunu unutmayın. İlgili içeriği oluşturmak için kullanılan tutucunun içindeki durum nesnesinin değeri yalnızca JankStats tarafından ayarlanır. O Bir uygulama, bunu içeren pencere için JankStats nesnesi oluşturursa durum nesnesini görebilirsiniz. hazırlanır ve oluşturulur. Aksi takdirde, JankStats bilgileri izlemeden durum nesnesine gerek yoktur ve uygulama veya kitaplık için gerekli değildir kodu kullanma.

Bu yaklaşım sayesinde JankStats'ın doldurabileceği bir tutucu alın. Harici kod her an sahibini isteyebilir. Arayanlar hafif Holder öğesini önbelleğe alabilir nesneye belirleyebilir ve öğenin değerine bağlı olarak, durumu ayarlamak için istediğiniz zaman kullanabilirsiniz. dahili state mülkü olup, bu mülk aşağıdaki örnek kodda olduğu gibidır; durum yalnızca sahibin dahili durum özelliği null olmadığında:

val metricsStateHolder = PerformanceMetricsState.getHolderForHierarchy(binding.root)
// ...
metricsStateHolder.state?.putState("Activity", javaClass.simpleName)

Kullanıcı arayüzü/uygulama durumunu kontrol etmek için bir uygulama, durum ekleyebilir (veya kaldırabilir) putState ve removeState yöntemleriyle gerçekleştirebilirsiniz. JankStats anlamına gelir. Bir kare durumun başlangıç ve bitiş zamanıyla çakışıyorsa çerçeve.

Herhangi bir eyalet için iki bilgi ekleyin: key ("RecyclerView" gibi bir eyalet kategorisi) ve value ( "kaydırma" gibi).

Hayır olduğunda, removeState() yöntemini kullanarak durumları kaldırın Böylece, yanlış veya yanıltıcı bilgilerin bildirilmemesi için daha uzun süre geçerli olurlar. çerçeve verileriyle karşılaştırabilirsiniz.

Daha önce eklenmiş bir key ile putState() çağrısı yapmak, şu numaranın yerine geçer: bu durumdaki mevcut value taneyi yenisiyle değiştirin.

State API'nin putSingleFrameState() sürümü, yalnızca bir kez (raporlanan sonraki karede) günlüğe kaydedilir. Sistem, otomatik olarak yanlışlıkla eski durumu devre dışı bırakmadığınızdan emin olmak için, kodunuz. Tek kare eşdeğerinin olmadığını unutmayın removeState(), JankStats tek kare durumlarını otomatik olarak kaldırdığından emin olur.

private val scrollListener = object : RecyclerView.OnScrollListener() {
    override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
        // check if JankStats is initialized and skip adding state if not
        val metricsState = metricsStateHolder?.state ?: return

        when (newState) {
            RecyclerView.SCROLL_STATE_DRAGGING -> {
                metricsState.putState("RecyclerView", "Dragging")
            }
            RecyclerView.SCROLL_STATE_SETTLING -> {
                metricsState.putState("RecyclerView", "Settling")
            }
            else -> {
                metricsState.removeState("RecyclerView")
            }
        }
    }
}

Eyaletler için kullanılan anahtarın, aynı zamanda gözden geçireceğiz. Özellikle, aynı key değerine sahip bir eyalet eklendiğinde, bu önceki değerin yerini alırsa düzeninizde farklı örnekleri olabilecek nesnelerin benzersiz key adları uygulama veya kitaplık. Örneğin, beş farklı RecyclerView içeren bir uygulama yerine, her biri için tanımlanabilir anahtarlar sağlamak istiyorsanız Her biri için RecyclerView ve ayrıntılı bir şekilde çerçeve verilerinin işaret ettiği örnek verilerin elde edilmesini sağlar.

Jank buluşsal yöntemler

Nelerin olumsuz olduğunu belirlemek üzere dahili algoritmayı ayarlamak için jankHeuristicMultiplier özelliği.

Sistem jank'ı, varsayılan olarak oluşturulması gerekenden iki kat daha uzun süren bir kare olarak tanımlar. güncel yenileme hızına ayarlanır. Saldırıyı uygulama oluşturma süresiyle ilgili bilgiler tamamen olmadığı için yenileme hızı açık. Bu nedenle, tampon ve yalnızca rapor eklemek daha iyidir sorunlara yol açabilir.

Bu değerlerin her ikisi de söz konusu yöntemler kullanılarak duruma uygun şekilde değiştirilebilir. veya olumsuz yönde etkilemek ya da olumsuz yönde etkilemek gereklidir.

Jetpack Compose'da kullanım

Şu an için Compose'da JankStats'ın kullanılması gereken kurulum işlemi yoktur. Yapılandırma değişiklikleri genelinde PerformanceMetricsState özelliğini korumak için şu şekilde hatırlayın:

/**
 * Retrieve MetricsStateHolder from compose and remember until the current view changes.
 */
@Composable
fun rememberMetricsStateHolder(): PerformanceMetricsState.Holder {
    val view = LocalView.current
    return remember(view) { PerformanceMetricsState.getHolderForHierarchy(view) }
}

JankStats'ı kullanmak için de mevcut durumu stateHolder öğesine aşağıda gösterildiği gibi ekleyin:

val metricsStateHolder = rememberMetricsStateHolder()

// Reporting scrolling state from compose should be done from side effect to prevent recomposition.
LaunchedEffect(metricsStateHolder, listState) {
    snapshotFlow { listState.isScrollInProgress }.collect { isScrolling ->
        if (isScrolling) {
            metricsStateHolder.state?.putState("LazyList", "Scrolling")
        } else {
            metricsStateHolder.state?.removeState("LazyList")
        }
    }
}

Jetpack Compose uygulamanızda JankStats kullanmayla ilgili tüm ayrıntılar için performans örnek uygulamamızı inceleyin.

Geri bildirim gönder

Aşağıdaki kaynakları kullanarak geri bildiriminizi ve düşüncelerinizi bizimle paylaşın:

Sorun izleyici
Hataları düzeltebilmemiz için sorunları bildirin.
ziyaret edin.
'nı inceleyin. ziyaret edin.