Yazılı Düşünme

Jetpack Compose, Android için modern bildirim temelli bir Kullanıcı Arayüzü Araç Setidir. Oluştur bildirim temelli bir API sağlayarak uygulamanızın kullanıcı arayüzünü yazmanızı ve sürdürmenizi kolaylaştırır ön ucu zorunlu olarak değiştirmeden uygulamanızın kullanıcı arayüzünü oluşturmanızı sağlar. görüntüleme. Bu terminolojiyle ilgili açıklama yapılması gerekiyor ancak önemli olduğunu unutmayın.

Bildirim temelli programlama paradigması

Önceden Android görünüm hiyerarşisi, bir kullanıcı arayüzü ağacı olarak temsil edilebiliyordu widget'lar. Uygulamanın durumu, kullanıcı özellikleri gibi nedenlerle değiştiğinden kullanıcı arayüzü hiyerarşisinin, mevcut verileri görüntüleyecek şekilde güncellenmesi gerekir. Kullanıcı arayüzünü güncellemenin en yaygın yolu, findViewById() ve button.setText(String) gibi yöntemleri çağırarak düğümleri değiştirin, container.addChild(View) veya img.setImageBitmap(Bitmap). Bu yöntemler widget'ın dahili durumunu değiştirin.

Görünümleri manuel olarak değiştirmek, hata olasılığını artırır. Bir veri parçası yer birden fazla yer görüyorsanız, görünümü gösteren görünümlerden birini güncellemeyi kolayca unutabilirsiniz. Aynı zamanda iki güncelleme birbiriyle çakıştığında, sağlayabilir. Örneğin, bir güncelleme, , kullanıcı arayüzünden kaldırıldı. Genel olarak yazılım bakımının karmaşıklığı güncellenmesi gereken görüntülemelerin sayısıyla birlikte artıyor.

Son birkaç yılda tüm sektör bir teknolojiye büyük ölçüde basitleştiren bu model, kullanıcı arayüzü oluşturma ve güncelleme. Bu teknik, çalışmalarınız için tüm ekranı baştan oluşturabilir, ardından yalnızca gerekli anlamına gelir. Bu yaklaşım, durum bilgili bir öğeyi manuel olarak güncellemenin karmaşıklığını önler hiyerarşik olarak görünür. Oluşturma, bildirim temelli bir kullanıcı arayüzü çerçevesidir.

Tüm ekranı yeniden oluşturma konusundaki zorluklardan biri, güç ve pil kullanımı açısından pahalıya mal olabilir. Etki azaltma Compose, kullanıcı arayüzünün hangi kısımlarının daha etkili olması herhangi bir zamanda yeniden çizilebilir. Bunun, ne tür bir şeyler oluşturmak istediğiniz Yeniden oluşturma bölümünde açıklandığı gibi kullanıcı arayüzü bileşenleriniz için geçerlidir.

Basit bir composable işlev

Oluşturma özelliğini kullanarak kullanıcı arayüzünüzü oluşturmak için Veri alan ve kullanıcı arayüzü öğeleri yayan composable işlevleri. Basit bir örnek String verilerini alan ve Text widget'ı yayan bir Greeting widget'ı görünen bir karşılama mesajı görüntülenir.

Metni gösteren bir telefonun ekran görüntüsü

Şekil 1. Veri aktaran ve bu verileri şu amaçlarla kullanan basit bir composable işlev: ekranda bir metin widget'ı oluşturun.

Bu işlevle ilgili dikkate değer birkaç nokta:

  • İşlev, @Composable ek açıklamasıyla belirtilir. Tümü Oluşturulabilir işlevler bu ek açıklamaya sahip olmalıdır; bu ek açıklama, Oluştur'a .

  • İşlev, verileri alır. Özelleştirilebilir fonksiyonlar parametreleri kabul edebilir, Böylece uygulama mantığının, kullanıcı arayüzünü tanımlamasını sağlar. Bu örnekte, widget'ımız , kullanıcıyı adıyla karşılamak için String kabul eder.

  • İşlev, kullanıcı arayüzünde metin gösterir. Bunu, Text() öğesini çağırarak yapar composable fonksiyonu, bu işlev metin kullanıcı arayüzü öğesini oluşturur. Oluşturulabilir işlevleri, diğer composable işlevleri çağırarak kullanıcı arayüzü hiyerarşisi yayar.

  • İşlev, hiçbir şey döndürmez. Kullanıcı arayüzünde yayın yapmayan işlevler istenen ekran durumunu açıkladıkları için herhangi bir şeyi döndürmeleri gerekir widget'ları oluşturmak yerine

  • Bu fonksiyon hızlıdır, idempotent, ve yan etkileri içermez.

    • Bu fonksiyon, ve genel değişkenler gibi diğer değerleri kullanmaz. veya random() için yapılan aramalar.
    • İşlev, kullanıcı arayüzünü herhangi bir yan etki olmadan tanımlar: özellikleri veya genel değişkenleri değiştirme.

    Genel olarak, tüm composable işlevleri bu özellikleri için Yeniden oluşturma bölümünde açıklanan nedenlerle.

Bildirim temelli paradigma değişimi

Birçok zorunlu nesne odaklı kullanıcı arayüzü araç setinde, kullanıcı arayüzünü ilk kullanıma hazırlarken oluşturmaya karar verdik. Bunu genellikle bir XML düzenini şişirerek yaparsınız. dosyası olarak kaydedebilirsiniz. Her widget kendi dahili durumunu korur ve alıcı ve uygulama mantığının widget'la etkileşime girmesine olanak tanıyan belirleyici yöntemleridir.

Compose'un bildirim temelli yaklaşımında widget'lar nispeten durum bilgisizdir ve belirleyici ya da alıcı fonksiyonlarını açığa çıkarmayın. Hatta, widget'lar nesne olarak gösterilmez. Kullanıcı arayüzünü, farklı bağımsız değişkenlerle aynı composable işlevine geri dönelim. Bu sayede, projenizin başarısını garantilemek birikim ve ülke gibi mimari kalıplar ViewModel, şurada açıklandığı gibi: Uygulama mimarisi rehberi. composable'larınız ise mevcut uygulama durumunu her seferinde bir kullanıcı arayüzüne dönüştürmekten sorumlu gözlemlenebilir veri güncellemelerinden bahsetmeye devam edelim.

Üst düzey nesnelerden alt öğelere kadar Compose kullanıcı arayüzünde veri akışını gösteren görsel.

Şekil 2. Uygulama mantığı, üst düzey composable işleve veri sağlar. Bu işlev, verileri kullanarak kullanıcı arayüzünü tanımlarken diğer composable'ları çağırır ve uygun verileri bu composable'lara iletir.

Kullanıcı, kullanıcı arayüzüyle etkileşimde bulunduğunda kullanıcı arayüzü, onClick gibi etkinlikleri öne çıkarır. Bu etkinlikler, uygulama mantığına bildirim göndermelidir. Uygulama mantığı, uygulamanın durumunu değiştirebilir. Durum değiştiğinde, composable işlevler yeni dışı verilerdir. Bu, kullanıcı arayüzü öğelerinin yeniden çizilmesine neden olur. Bu işleme recomposition gibi bazı örneklerdir.

Kullanıcı arayüzü öğelerinin, uygulama mantığı tarafından işlenen etkinlikleri tetikleyerek etkileşime nasıl tepki verdiğini gösteren resim.

Şekil 3. Kullanıcı bir kullanıcı arayüzü öğesiyle etkileşimde bulundu ve bu da etkinliğin tetiklendi. Uygulama mantığı etkinliğe yanıt verir, ardından composable işlevleri değerleri, gerekirse yeni parametrelerle otomatik olarak tekrar çağrılır.

Dinamik içerik

Oluşturulabilir işlevler XML yerine Kotlin dilinde yazıldığından diğer Kotlin kodları kadar dinamik olabilir. Örneğin, bir kullanıcı arayüzü oluşturmak istediğinizi bir web sitesini ziyaret edin:

@Composable
fun Greeting(names: List<String>) {
    for (name in names) {
        Text("Hello $name")
    }
}

Bu işlev, ad listesini alır ve her kullanıcı için bir karşılama mesajı oluşturur. Özelleştirilebilir işlevler oldukça karmaşık olabilir. if ifadelerini kullanarak belirli bir kullanıcı arayüzü öğesini göstermek isteyip istemediğinize karar verebilirsiniz. Döngüleri kullanabilirsiniz. Şunları yapabilirsiniz: yardımcı işlevleri çağırın. Temel altyapının sunduğu tüm esneklikten dili'ne dokunun. Bu güç ve esneklik Jetpack'in temel avantajlarından biridir. Oluştur'u tıklayın.

Yeniden düzenleme

Zorunlu kullanıcı arayüzü modelinde bir widget'ı değiştirmek için widget'ta bir belirleyici çağırırsınız dahili durumunu değiştirmek için. Compose'da composable işlevini tekrar çağırırsınız. yeni verileri kullanır. Bu, işlevin (Widget'lar) yeniden oluşturulmasına neden olur İşlev tarafından yayınlanan hatalar, gerekirse yeni verilerle yeniden çizilir. Oluşturma sadece değişen bileşenleri akıllı bir şekilde yeniden ortaya çıkarabilir.

Örneğin, bir düğme görüntüleyen şu composable işlevi ele alalım:

@Composable
fun ClickCounter(clicks: Int, onClick: () -> Unit) {
    Button(onClick = onClick) {
        Text("I've been clicked $clicks times")
    }
}

Düğme her tıklandığında arayan, clicks değerini günceller. Compose, yeni değeri göstermek için Text işleviyle lambda'yı tekrar çağırır; bu sürece yeniden oluşturma adı verilir. değeri yeniden oluşturulmaz.

Konuştuğumuz gibi, kullanıcı arayüzü ağacının tamamını yeniden oluşturmak, ve pil ömrünü uzatır. Compose şu sorunu çözer: bu akıllı yeniden besteyle ilgili bir sorun var.

Yeniden oluşturma, bir araya getirildiğinde composable işlevlerinizi girişlerin değişmesi. Bu durum, işlevin girişleri değiştiğinde ortaya çıkar. Oluştururken yeni girişlere göre yeniden oluşturduğunda, yalnızca değişmiş olabilir ve gerisini atlar. Tüm işlevleri veya lambda'ları atlayarak yoksa Compose verimli bir şekilde yeniden oluşturabilir.

composable işlevlerin çalıştırılmasından kaynaklanan yan etkilere asla güvenmeyin çünkü fonksiyonun yeniden bestesi atlanabilir. Aksi takdirde, kullanıcılar ve öngörülemeyen davranışlara yol açabilir. Yan etki, görünür olan bir değişikliktir. Örneğin, şu işlemler tümü tehlikeli yan etkileridir:

  • Paylaşılan bir nesnenin özelliğine yazma
  • ViewModel içindeki bir gözlemlenebilir öğeyi güncelleme
  • Paylaşılan tercihler güncelleniyor

Oluşturulabilir işlevler her karede olduğu kadar yeniden yürütülebilir. Örneğin animasyon oluşturuluyor. Özelleştirilebilir işlevler hızlı olmalıdır. tıkanıklık yaratıyor. Okuma gibi pahalı işlemler yapmanız gerekiyorsa bunu arka plan koordinatında yapın ve değeri ileterek sonucu, composable işlevine parametre olarak eklenir.

Örneğin bu kod, SharedPreferences composable, paylaşılan kaynaklardaki okuma veya yazma işlemlerini yapmamalıdır ekleyebilirsiniz. Bunun yerine bu kod, okuma ve yazma işlemini bir ViewModel öğesine taşır arka planda eş yordam üzerinde çalışırken. Uygulama mantığı, mevcut değeri bir geri çağırma işlevini kullanın.

@Composable
fun SharedPrefsToggle(
    text: String,
    value: Boolean,
    onValueChanged: (Boolean) -> Unit
) {
    Row {
        Text(text)
        Checkbox(checked = value, onCheckedChange = onValueChanged)
    }
}

Bu dokümanda, Oluştur'u kullanırken göz önünde bulundurmanız gereken bazı noktalar anlatılmaktadır:

  • Oluşturulabilir işlevler herhangi bir sırada yürütülebilir.
  • Özelleştirilebilir işlevler paralel olarak yürütülebilir.
  • Yeniden düzenleme, mümkün olduğunca çok composable işlevi ve lambdayı atlar.
  • Yeniden düzenleme iyimser olduğu için iptal edilebilir.
  • Bir composable işlev sıkça, hatta her karede olduğu gibi çalıştırılabilir olabilir.

Aşağıdaki bölümlerde, 2023'e kadar mobil uyumlu bile olabilir. Her durumda en iyi uygulama, composable hızlı, etkili ve yan etki içermeyen bir şekilde çalışır.

Oluşturulabilir işlevler herhangi bir sırada yürütülebilir

Bir composable fonksiyonun koduna bakarsanız, kodu gösterildiği sırada çalıştırılır. Ancak bu, her zaman doğru olmayabilir. composable işlevi, diğer composable işlevlerine işlevleri herhangi bir sırada çalışabilir. Oluşturma işleminde, iletide bir araya getirilen bazı kullanıcı arayüzü öğeleri diğerlerinden daha önceliklidir ve bunları ilk önce çizer.

Örneğin, bir sekmede üç ekran çizmek için böyle bir kodunuz olduğunu varsayalım düzen:

@Composable
fun ButtonRow() {
    MyFancyNavigation {
        StartScreen()
        MiddleScreen()
        EndScreen()
    }
}

StartScreen, MiddleScreen ve EndScreen çağrıları herhangi bir sipariş. Örneğin, StartScreen() için global ayar yapamazsınız değişkenini (bir yan etki) oluşturur, MiddleScreen() bundan yararlanmasını sağlar unutmayın. Bunun yerine, bu işlevlerin her birinin bağımsız olması gerekir.

Özelleştirilebilir işlevler paralel olarak çalışabilir

Compose, composable işlevleri paralel olarak çalıştırarak yeniden besteyi optimize edebilir. Bu sayede Compose birden fazla çekirdekten yararlanabilir ve composable işlevleri çalıştırabilir. daha düşük öncelikte değil.

Bu optimizasyon, composable işlevinin arka plan ileti dizileri. Bir composable işlev ViewModel üzerinde bir işlevi çağırırsa Oluştur, bu işlevi aynı anda birkaç ileti dizisinden çağırabilir.

Uygulamanızın doğru bir şekilde çalışmasını sağlamak için tüm composable işlevleri yan etkisi yoktur. Bunun yerine, onClick her zaman UI iş parçacığında yürütülür.

Bir composable işlev çağrıldığında, çağrı farklı bir ileti dizisidir. Bu, bir composable'da değişkenleri değiştiren kod anlamına gelir. lambda'dan kaçınılmalıdır. Çünkü bu tür kodlar iş parçacığı açısından güvenli değildir ve bu parçalanabilir lambdanın izin verilmeyen bir yan etkisidir.

Listeyi ve sayısını görüntüleyen bir composable'ın örneğini aşağıda bulabilirsiniz:

@Composable
fun ListComposable(myList: List<String>) {
    Row(horizontalArrangement = Arrangement.SpaceBetween) {
        Column {
            for (item in myList) {
                Text("Item: $item")
            }
        }
        Text("Count: ${myList.size}")
    }
}

Bu kod yan etki içermez ve giriş listesini kullanıcı arayüzüne dönüştürür. Çok iyi küçük bir liste görüntüleme kodu vardır. Ancak, işlev bir yerel değişkense bu kod ileti dizisi açısından güvenli veya doğru olmaz:

@Composable
@Deprecated("Example with bug")
fun ListWithBug(myList: List<String>) {
    var items = 0

    Row(horizontalArrangement = Arrangement.SpaceBetween) {
        Column {
            for (item in myList) {
                Text("Item: $item")
                items++ // Avoid! Side-effect of the column recomposing.
            }
        }
        Text("Count: $items")
    }
}

Bu örnekte, items her yeniden oluşturmada değiştirilmiştir. Bu, Google'ın veya liste güncellendiğinde. Her iki durumda da kullanıcı arayüzü yanlış sayıyı görüntülemek. Bu nedenle, bunun gibi yazma işlemleri Oluşturma; bu yazmaları yasaklayarak çerçevenin ileti dizilerini değiştirmesine izin veririz. composable lambda'lar yürütmesi için tasarlandı.

Yeniden düzenleme mümkün olduğunca fazla atlıyor

Kullanıcı arayüzünün bazı bölümleri geçersiz olduğunda Compose, güncellenmesi gereken bölümlerdir. Bu durumda, tek bir reklamı tekrar Düğmenin üzerindeki veya altındaki composable'lardan hiçbiri yürütülmeden composable tıklayın.

Her composable işlev ve lambda kendi başına yeniden oluşturulabilir. Bir yeniden düzenlemenin bazı öğeleri nasıl atlayabileceğini gösteren örnek bir liste oluştururken:

/**
 * Display a list of names the user can click with a header
 */
@Composable
fun NamePicker(
    header: String,
    names: List<String>,
    onNameClicked: (String) -> Unit
) {
    Column {
        // this will recompose when [header] changes, but not when [names] changes
        Text(header, style = MaterialTheme.typography.bodyLarge)
        Divider()

        // LazyColumn is the Compose version of a RecyclerView.
        // The lambda passed to items() is similar to a RecyclerView.ViewHolder.
        LazyColumn {
            items(names) { name ->
                // When an item's [name] updates, the adapter for that item
                // will recompose. This will not recompose when [header] changes
                NamePickerItem(name, onNameClicked)
            }
        }
    }
}

/**
 * Display a single name the user can click.
 */
@Composable
private fun NamePickerItem(name: String, onClicked: (String) -> Unit) {
    Text(name, Modifier.clickable(onClick = { onClicked(name) }))
}

Bu kapsamların her biri, yeniden oluşturma sırasında yürütülecek tek şey olabilir. Oluşturma, üst öğelerinden hiçbirini yürütmeden Column lambdasına atlayabilir header değiştiğinde. Ayrıca, Column yürütülürken Compose'un şunu yapması gerekir: names değişmediyse LazyColumn öğelerini atla.

Tekrar etmek gerekirse, composable'ın tüm işlevlerinin veya lambda'ların çalıştırılmasında yan etki bulunmamalıdır. Bir yan etki gerçekleştirmeniz gerektiğinde, bu işlemi bir geri aramadan tetikleyin.

Yeniden düzenleme iyimser

Compose, bir composable'ın parametrelerinin parametrelerini değişmiş olabilir. Yeniden düzenleme iyimser. Bu da Compose'un şunları beklediği anlamına gelir: işlemini tamamlayın. Bir parametre değiştiğinde, Compose yeniden oluşturma işlemini iptal edebilir. yeniden oluşturun ve yeni parametreyle yeniden başlatın.

Yeniden oluşturma iptal edildiğinde, Compose, kullanıcı arayüzü ağacını bile olabilir. Kullanıcı arayüzüne bağlı olarak yan etkileriniz varsa görüntülendiğinde, beste iptal edilse bile yan etki uygulanır. Bu durum uygulama durumunun tutarsız olmasına yol açabilir.

Tüm composable işlevlerin ve lambda'ların eşgüdümlü ve yan etkiye sahip olduğundan emin olun serbest bir şekilde yeniden düzenlemesini sağlar.

Özelleştirilebilir işlevler oldukça sık çalışabilir

Bazı durumlarda, composable işlev bir kullanıcı arayüzünün her karesi için çalışabilir animasyon ekler. Fonksiyon, bu işlev, kullanıcı arayüzü gecikmelerine neden olabilir.

Örneğin, widget'ınız cihaz ayarlarını okumaya çalıştıysa bu ayarları saniyede yüzlerce kez okuyabilir. Bu da en iyi uygulamaları paylaşacağız.

composable fonksiyonunuz veri gerektiriyorsa verilere ilişkin parametreleri tanımlamalıdır. Sonra pahalı işleri başka bir ileti dizisine oluşturabilir ve mutableStateOf veya LiveData kullanarak verileri Compose'a iletebilirsiniz.

Daha fazla bilgi

Oluşturma ve composable işlevlerde nasıl düşünüleceği hakkında daha fazla bilgi için inceleyebilirsiniz.

Videolar

ziyaret edin. ziyaret edin.