ComposeView Nedir ve Nasıl Kullanılır ? (Java-Kotlin)

Burak Can Görgülü
3 min readAug 24, 2023

Bu yazımda XML içinde ComposeView nasıl kullanılır ve Java/Kotlin kodumuzun içine nasıl Composable enjekte edebiliriz onu anlatacağım.

ComposeView bir Jetpack Compose bileşenidir. XML kodlarının içinde Composable fonksiyonlarımızı çalıştırabilmemizi sağlar.

Eğer projenizin bir kısmı Views bir kısmı da Compose ile yazılmış ise View ile yazdığınız kısımların içinde Composable fonksiyonlarınızı kullanmanıza olanak sağlar ve kullanımı çok rahattır.

🔍 ComposeView Nasıl Oluşturulur ?

ComposeView tanımlarken XML içinde herhangi bir View tanımlıyormuş gibi tanımlanır.

Xml içinde ComposeView
XML içinde ComposeView

Bu tanımlamayı yaptıktan sonra Kotlin veya Java kodunuzun içinde bu View’ a erişerek Composable fonksiyonlarınıza ulaşabilirsiniz.

Tabi bu bağlantıyı sağlamak için bazı noktalara dikkat etmek gerekiyor. Java ve Kotlin kodunun içinde farklı şekilde düzenlemeler yapmak gerekebiliyor. Bunun içinde her iki kısım içinde de rahatça çalışmasını sağlayacak bir manager yazıyoruz.

✅ ComposeViewManager :

object ComposeViewManager {

fun setComposableContent(
composeView: ComposeView,
content: ComposableProvider,
) {
composeView.apply {
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
MaterialTheme {
content.ProvideComposableContent()
}
}
}
}

fun setComposableContentForKotlin(
composeView: ComposeView,
content: @Composable ComposableProvider.() -> Unit,
) {
composeView.apply {
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
MaterialTheme {
ComposableProviderImpl().content()
}
}
}
}
}

Burada oluşturduğumuz manager sınıfında 2 tane fonksiyonumuz var. İlk fonksiyonumuz hem Kotlin hem de Java kodunun içinde kullanılabiliyor ama Java ile kullanılmasını daha doğru buluyorum.
İkinci fonksiyonumuz ise Kotlin kodumuzun içinde kurduğum başka bir yapı ile birlikte ComposableScope gibi davranan bir alan oluşturabilmemize olanak sağlıyor.

ComposeView parametresini XML de oluşturduğumuz ComposeView’a erişebilmek için kullanıyoruz. ComposableProvider’ı ve onunla oluşturduğumuz ComposableScope özelliğini ise ileride detaylı bir şekilde anlatacağım.

  1. composeView.apply { ... }: Bu blok, bir Compose görünümünün özelliklerini yapılandırmak için kullanılır. “composeView”, bir Compose Görünümünün referansını temsil eder ve bu blok içinde düzenlemeler yapılacaktır.
  2. setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed): Bu satır, Compose Görünümünün nasıl oluşturulacağını ve sonlandırılacağını belirtir. DisposeOnViewTreeLifecycleDestroyed stratejisi, ViewTree’nin yaşam döngüsü sona erdiğinde otomatik olarak temizlenmesini sağlar. Yani, ViewTree yok edildiğinde, ilgili Compose bileşenleri de bellekten temizlenir.
  3. setContent { ... }: Bu blok, Görünümün içeriğini belirler. ComposeView, bu içerik bloğu tarafından tanımlanan bileşenlerin hiyerarşisini oluşturacaktır.

ComposableProvider :

interface ComposableProvider {
@Composable
fun ProvideComposableContent()
}

Burada bir interface içinde Composable fonksiyon oluşturarak Java veya Kotlin kodumuzun içinde Composable’larımızı bir callback fonksiyon gibi geçebileceğimiz bir düzen oluşturuyoruz.

ComposableProviderImpl :

private class ComposableProviderImpl : ComposableProvider {
@Composable
override fun ProvideComposableContent() {
}
}

Burada önceden oluşturduğumuz ComposableProvider interface yardımıyla bir sınıf oluşturuyoruz. Bu sayede kendi Composable alanımızı oluşturmuş oluyoruz ve Kotlin kodumuzun içinde ComposableScope gereklidir hatasını da engellemiş oluyoruz.

✅ Java :

Java kodumuzun içersinde kullanırken şu şekilde bir yaklaşım sergileyebiliriz.

 ComposeViewManager.INSTANCE.setComposableContent(
binding.composeView,
()-> {ComposeViewExampleKt.ComposeViewExample();}
);

Burada Composable fonksiyonumuzun Java kodunda algılanabilmesi için callback fonksiyon içinde bulunduğuKotlindosyası.Composable() şeklinde bir çağırım yapmamız gerekiyor.

Eğer Composable fonksiyonumuz parametre alıyorsa bu şekilde tanımlama yaparak istediğimiz parametreyide geçebiliriz. Ancak parametre almayan bir Composable ise o zaman lambda gösterimi yapılabilir.

// Lambda gösterimi
ComposeViewManager.INSTANCE.setComposableContent(
binding.composeView,
ComposeViewExampleKt::ComposeViewExample
);

Kotlin :

Kotlin kodumuzun içersinde kullanırken şu şekilde bir yaklaşım sergileyebiliriz.

ComposeViewManager.setComposableContentForKotlin(
composeView = binding.composeView,
content = { ComposeViewExample() }
)

Burada bir ComposableScope oluşturduğumuz için ComposeViewExample’ı herhangi bir uyarı almadan geçebilmiş olduk. Kotlin kodumuzun içinde istediğimiz Composable fonksiyonları kullanabiliyoruz.

🍬 Ekstra :

Alternatif olarak setComposableContent fonksiyonunu kullanarak da Kotlin içinde ComposeView kullanımı yapabiliyoruz.

ComposeViewManager.setComposableContent(
binding.composeView,
object : ComposableProvider {
@Composable
override fun ProvideComposableContent() {
ComposeViewExample()
}
}
)

Burada parametre olarak bir ComposableProvider beklenildiği için buraya bir object geçilmesi gerekiyor.

Java’da yaptığımız gibi bir yaklaşımı burada sergileyemiyoruz çünkü ComposableScope içinde çağırım yapmamız bekleniyor.

Bu yüzdende bu şekilde bir çözüm yaparak Kotlin kodumuzun içinde de ComposeView kullanımını sağlıyoruz.

Buraya kadar okuduğunuz için teşekkür ederim. Umarım bilgiler faydalı olmuştur. Bir sonraki yazımızda görüşmek dileğiyle…😄

--

--