Jetpack Compose, Kotlin etrafında geliştirildi. Kotlin bazı durumlarda özel daha kolay bir şekilde yazabileceğiniz deyimler. Başka bir Kotlin'e çevirirseniz, kulağa hoş geldiniz, büyük olasılıkla Compose'un gücünden yararlanma fırsatından yararlanabilecektir ve anlamak zordur. Daha fazla kazanıyorum Kotlin’in tarzına aşina olmak bu tehlikelerden kaçınmanıza yardımcı olabilir.
Varsayılan bağımsız değişkenler
Kotlin işlevi yazarken, işlev bağımsız değişkenleri için varsayılan değerler belirtebilirsiniz. Bu değerler, çağıran bu değerleri açıkça iletmezse kullanılır. Bu özellik, Bu da, aşırı yüklenmiş işlevler ihtiyacını ortadan kaldırır.
Örneğin, kare çizen bir işlev yazmak istediğinizi varsayalım. O fonksiyonunun uzunluğunun belirtildiği sideLength adlı tek bir gerekli parametresi olabilir temsil eder. Bu parametrede thickness gibi isteğe bağlı parametreler kullanılabilir. edgeColor vb.; arayan kişi bunları belirtmezse işlevi varsayılan değerleri kullanır. Diğer dillerde birkaç işlev yazmanız gerekebilir:
// We don't need to do this in Kotlin! void drawSquare(int sideLength) { } void drawSquare(int sideLength, int thickness) { } void drawSquare(int sideLength, int thickness, Color edgeColor) { }
Kotlin'de tek bir işlev yazabilir ve şunları sağlar:
fun drawSquare( sideLength: Int, thickness: Int = 2, edgeColor: Color = Color.Black ) { }
Bu, sizi gereksiz birden fazla işlev yazma zahmetinden kurtarmanın yanı sıra,
özelliği, kodunuzun daha kolay okunmasını sağlar. Arayan bir bağımsız değişken için değer belirtmezse varsayılan değeri kullanmak istediğini gösterir. Ayrıca, adlandırılmış parametreler neler olduğunu daha kolay görmenizi sağlar. Kodu incelediğinizde aşağıdaki gibi bir işlev çağrısı görürseniz drawSquare()
kodunu kontrol etmeden parametrelerin ne anlama geldiğini bilemeyebilirsiniz:
drawSquare(30, 5, Color.Red);
Bunun aksine, bu kod kendini belgelemektedir:
drawSquare(sideLength = 30, thickness = 5, edgeColor = Color.Red)
Çoğu Compose kitaplığı varsayılan bağımsız değişkenleri kullanır ve aynı işlevi görür. Bu sayede, composable'ları özelleştirilebilir, ancak yine de varsayılan davranışın çağrılmasını basitleştirir. Dolayısıyla, örneğin, şunun gibi basit bir metin öğesi oluşturabilirsiniz:
Text(text = "Hello, Android!")
Bu kod aşağıdakiyle aynı etkiye sahiptir. Çok daha ayrıntılı olan bu kod,
hakkında daha fazla
Text
Parametreler açık bir şekilde ayarlanır:
Text( text = "Hello, Android!", color = Color.Unspecified, fontSize = TextUnit.Unspecified, letterSpacing = TextUnit.Unspecified, overflow = TextOverflow.Clip )
İlk kod snippet'i çok daha basit ve okunması kolay olmasının yanı sıra
kendi belgeleme sürecidir. Yalnızca text
parametresini belirterek
diğer tüm parametreleri istiyorsanız varsayılan değerleri kullanmanız gerekir. Buna karşın
ikinci snippet, bu etiketler için değerleri açıkça ayarlamak istediğinizi
diğer parametreleri kullanabilirsiniz, ancak ayarladığınız değerler
işleve geri dönelim.
Üst düzey işlevler ve lambda ifadeleri
Kotlin, üst sırayı destekler
işlevlerinin
parametre olarak diğer işlevleri alırlar. Oluşturma, bu yaklaşımı temel alır. Örneğin, Button
birleşebilir işlevi bir onClick
lambda parametresi sağlar. Değer
parametresi bir fonksiyondur ve kullanıcı tıkladığında düğme tarafından çağrılır:
Button( // ... onClick = myClickFunction ) // ...
Daha yüksek düzeydeki işlevler lambda ifadeleri ve ifadelerle doğal bir şekilde eşlenir.
bu da bir fonksiyona dönüşüyor. İşleve yalnızca bir kez ihtiyaç duyarsanız
üst düzey işleve aktarmak üzere başka bir yerde tanımlamak için kullanılır. Bunun yerine
fonksiyonu bir lambda ifadesiyle tanımlamanız yeterlidir. Önceki örnekte, myClickFunction()
'ün başka bir yerde tanımlandığı varsayılmaktadır. Ancak yalnızca
fonksiyonunu bir lambda ile satır içi olarak tanımlamak daha basittir
ifade:
Button( // ... onClick = { // do something // do something else } ) { /* ... */ }
Sondaki lambdalar
Kotlin, son parametresi bir lambda parametresidir. Bu şekilde bir lambda ifadesi iletmek parametresini kullanmak için trailing lambda söz dizimini kullanın. Lambda ifadesini parantez içine almak yerine bu ifadeyi daha fazla bilgi edineceksiniz. Bu durum, Compose'da sık karşılaşılan bir durumdur. ile uyumlu hale getirebilirsiniz.
Örneğin, tüm düzenlerin son parametresi;
Column()
composable işlev, content
, alt kullanıcı arayüzünü yayan bir işlevdir
öğeler. Üç metin öğesi içeren bir sütun oluşturmak istediğinizi varsayalım,
ve biraz biçimlendirme uygulamanız gerekir. Bu kod çalışır ancak
zahmetli:
Column( modifier = Modifier.padding(16.dp), content = { Text("Some text") Text("Some more text") Text("Last text") } )
content
parametresi işlev imzasında son parametre olduğundan ve değerini lambda ifadesi olarak ilettiğimizde parantezlerden çıkarabiliriz:
Column(modifier = Modifier.padding(16.dp)) { Text("Some text") Text("Some more text") Text("Last text") }
İki örnek de aynı anlama sahiptir. Küme ayraçları lambda'yı tanımlar
content
parametresine aktarılan bir ifadedir.
Aslında, ilettiğiniz tek parametre bu son lambda ise (yani son parametre bir lambda ise ve başka parametre iletmiyorsanız) parantezleri tamamen atlayabilirsiniz. Örneğin, Arkadaş Bitkiler projenizde
Column
öğesine bir değiştirici iletmeniz gerekmiyordu. Kodu şöyle yazabilirsiniz:
bu:
Column { Text("Some text") Text("Some more text") Text("Last text") }
Bu söz dizimi, Compose'da oldukça yaygındır. Özellikle
Column
Son parametre, öğenin
alt öğeleri (alt öğeler) ise fonksiyon çağrısından sonra küme ayraçları içinde belirtilir.
Nişan dürbünleri ve alıcılar
Bazı yöntemler ve özellikler yalnızca belirli bir kapsamda kullanılabilir. Sınırlı kapsam, gerektiğinde işlevsellik sunmanızı ve kazara erişimi önlemenizi sağlar. o işlevin uygun olmadığı durumlarda kullanmayı düşünebilirsiniz.
Compose'da kullanılan bir örneği düşünün. Row
düzenini çağırdığınızda
composable, içeriğinizin lambda değeri bir RowScope
içinde otomatik olarak çağrılır.
Bu sayede Row
, yalnızca Row
içinde geçerli olan işlevleri sunabilir.
Aşağıdaki örnekte, Row
'ün align
değiştiricisi için satıra özgü bir değeri nasıl gösterdiği gösterilmektedir:
Row { Text( text = "Hello world", // This Text is inside a RowScope so it has access to // Alignment.CenterVertically but not to // Alignment.CenterHorizontally, which would be available // in a ColumnScope. modifier = Modifier.align(Alignment.CenterVertically) ) }
Bazı API'ler, alıcı kapsamında çağrılan lambdaları kabul eder. Bu lambda'lar veya başka bir yerde tanımlanan özellik ve işlevlere parametre bildirimi:
Box( modifier = Modifier.drawBehind { // This method accepts a lambda of type DrawScope.() -> Unit // therefore in this lambda we can access properties and functions // available from DrawScope, such as the `drawRectangle` function. drawRect( /*...*/ /* ... ) } )
Daha fazla bilgi için şununla birlikte işlev değişmez değerleri: alıcı hakkındaki makalemizi incelemenizi öneririz.
Yetki verilen mülkler
Kotlin, Google'dan yetki verilmiş
özellikleri hakkında daha fazla bilgi edinin.
Bu mülkler alan gibi çağrılır ancak değerleri bir ifadenin değerlendirilmesiyle dinamik olarak belirlenir. Bunları tanıyabilirsiniz
özelliklerini kullanarak by
söz dizimini kullanır:
class DelegatingClass { var name: String by nameGetterFunction() // ... }
Diğer kod, mülküne şu kodla erişebilir:
val myDC = DelegatingClass() println("The name property is: " + myDC.name)
println()
yürütüldüğünde, değeri döndürmek için nameGetterFunction()
çağrılır
seçin.
Bu yetki verilmiş özellikler özellikle devlet destekli mülkler:
var showDialog by remember { mutableStateOf(false) } // Updating the var automatically triggers a state change showDialog = true
Veri sınıflarını imha etme
Bir verileri tanımlarsanız
sınıfına girip
bu verilere erişimi indirim aracı
beyan başlıklı makaleyi inceleyin. Örneğin,
Örneğin, bir Person
sınıfı tanımladığınızı varsayalım:
data class Person(val name: String, val age: Int)
Bu türde bir nesneniz varsa değerlerine aşağıdaki gibi kodla erişebilirsiniz: bu:
val mary = Person(name = "Mary", age = 35) // ... val (name, age) = mary
Oluşturma işlevlerinde genellikle bu tür bir kod görürsünüz:
Row { val (image, title, subtitle) = createRefs() // The `createRefs` function returns a data object; // the first three components are extracted into the // image, title, and subtitle variables. // ... }
Veri sınıfları, birçok başka faydalı işlev sunar. Örneğin,
bir veri sınıfı tanımlarsanız derleyici,
equals()
ve copy()
. Daha fazla bilgiyi veriler
sınıfları dokümanlarına göz atın.
Singleton nesneleri
Kotlin, her zaman bir ve
yalnızca bir örnek. Bu single'lar, object
anahtar kelimesiyle belirtilir.
Oluşturma işleminde genellikle bu tür nesneler kullanılır. Örneğin,
MaterialTheme
tek bir nesne olarak tanımlanır; MaterialTheme.colors
, shapes
ve
typography
özelliklerinin tümü geçerli temanın değerlerini içerir.
Tür açısından güvenli oluşturucular ve DSL'ler
Kotlin, tür açısından güvenli oluşturucularla alana özgü diller (DSL'ler) oluşturmanıza olanak tanır. DSL'ler karmaşık hiyerarşik verilerin oluşturulmasına olanak tanır daha sürdürülebilir ve okunabilir bir şekilde sunabilirsiniz.
Jetpack Compose,
LazyRow
ve LazyColumn
.
@Composable fun MessageList(messages: List<Message>) { LazyColumn { // Add a single item as a header item { Text("Message List") } // Add list of messages items(messages) { message -> Message(message) } } }
Kotlin, aşağıdakileri kullanarak tür güvenli derleyiciler oluşturur:
alıcıyla işlev değişmez değerini kontrol edin.
Canvas
composable,
DrawScope
alıcı onDraw: DrawScope.() -> Unit
olarak görünür ve kod bloğunun
DrawScope
içinde tanımlanan üye işlevlerini çağırın.
Canvas(Modifier.size(120.dp)) { // Draw grey background, drawRect function is provided by the receiver drawRect(color = Color.Gray) // Inset content by 10 pixels on the left/right sides // and 12 by the top/bottom inset(10.0f, 12.0f) { val quadrantSize = size / 2.0f // Draw a rectangle within the inset bounds drawRect( size = quadrantSize, color = Color.Red ) rotate(45.0f) { drawRect(size = quadrantSize, color = Color.Blue) } } }
Tür güvenli derleyiciler ve DSL'ler hakkında daha fazla bilgi için Kotlin belgeleri.
Kotlin eş yordamları
Eş yordamlar, Kotlin. Eş yordamlar, ileti dizilerini engellemeden yürütmeyi askıya alabilir. CEVAP duyarlı kullanıcı arayüzü, doğası gereği eşzamansızdır ve Jetpack Compose bu sorunu eş yordamları API düzeyinde benimsemek
Jetpack Compose, kullanıcı arayüzü katmanında iş parçacıklarını güvenli bir şekilde kullanmanızı sağlayan API'ler sunar.
rememberCoroutineScope
işlevi, etkinlik işleyicilerde veCoroutineScope
Askıya alma API'leri oluşturun. Şunu kullanarak aşağıdaki örneğe bakın:
ScrollState
animateScrollTo
API.
// Create a CoroutineScope that follows this composable's lifecycle val composableScope = rememberCoroutineScope() Button( // ... onClick = { // Create a new coroutine that scrolls to the top of the list // and call the ViewModel to load data composableScope.launch { scrollState.animateScrollTo(0) // This is a suspend function viewModel.loadData() } } ) { /* ... */ }
Görev akışları, kod bloğunu varsayılan olarak sıralı olarak yürütür. Koşu
askıya alma işlevini çağıran eş yordam,
askıya alma işlevi geri gelir. Askıya alma işlevi
farklı bir CoroutineDispatcher
çalıştırmasını sağlayın. Önceki örnekte, animateScrollTo
işlevi döndürülene kadar loadData
yürütülmez.
Kodu eşzamanlı olarak yürütmek için yeni eş yordamların oluşturulması gerekir. Örnekte
ekranın üst kısmına doğru kaydırmak ve
viewModel
, iki eş yordam gerekli.
// Create a CoroutineScope that follows this composable's lifecycle val composableScope = rememberCoroutineScope() Button( // ... onClick = { // Scroll to the top and load data in parallel by creating a new // coroutine per independent work to do composableScope.launch { scrollState.animateScrollTo(0) } composableScope.launch { viewModel.loadData() } } ) { /* ... */ }
Eş yordamlar, eşzamansız API'lerin birleştirilmesini kolaylaştırır. Sonraki
örneğin, pointerInput
değiştiricisini animasyon API'leriyle birleştirerek
Kullanıcı ekrana dokunduğunda bir öğenin konumuna animasyon uygulayın.
@Composable fun MoveBoxWhereTapped() { // Creates an `Animatable` to animate Offset and `remember` it. val animatedOffset = remember { Animatable(Offset(0f, 0f), Offset.VectorConverter) } Box( // The pointerInput modifier takes a suspend block of code Modifier .fillMaxSize() .pointerInput(Unit) { // Create a new CoroutineScope to be able to create new // coroutines inside a suspend function coroutineScope { while (true) { // Wait for the user to tap on the screen val offset = awaitPointerEventScope { awaitFirstDown().position } // Launch a new coroutine to asynchronously animate to // where the user tapped on the screen launch { // Animate to the pressed position animatedOffset.animateTo(offset) } } } } ) { Text("Tap anywhere", Modifier.align(Alignment.Center)) Box( Modifier .offset { // Use the animated offset as the offset of this Box IntOffset( animatedOffset.value.x.roundToInt(), animatedOffset.value.y.roundToInt() ) } .size(40.dp) .background(Color(0xff3c1361), CircleShape) ) }
Eş yordamlar hakkında daha fazla bilgi edinmek için Android'de Kotlin eş yordamları rehberi.
Sizin için önerilenler
- Not: JavaScript kapalıyken bağlantı metni gösterilir
- Malzeme Bileşenleri ve düzenleri
- Compose'da yan etkiler
- Oluşturma düzeniyle ilgili temel bilgiler