Kotlin Coroutines Nedir?

Selamlar, bugün sizlerle Kotlin’le hayatımıza giren bir yapı olan Coroutine’i öğreneceğiz. Hazırsanız haydi başlayalım. 🤓

Coroutine, 2017 senesinde gerçekleştirilen KotlinConf’ta tanıtıldı. 🥳

KotlinConf 2017

KotlinConf: Kotlin dilinde geliştirilen yenilikler ve güncellemelerin tanıtıldığı etkinliktir. 2017'de ilki düzenlenmekle beraber her sene aktif şekilde yapılmaktadır.

Coroutine, geliştirmesi ve anlaşılması oldukça kolay, uygulamayı engellemeden, durdurmadan Asynchronous(eşzamanlı olmayan) şekilde kod yazmaya yarayan bir modeldir. 🛠

Kotlin Coroutines

Asynchronous: Kod akışının sırayla işlenmediği, işlemlerin birbirini beklemediği, kodun işlem durumlarına göre devam ettiği programlardır.

Coroutine’nin temel amacı, karmaşık ağ protokollerini uygulamak ve arkaplanda meydana gelen çakışmaların önüne geçmeyi sağlamaktır.

Bu tip işlemlerin yapıldığı tüm class, function kotlinx.coroutines 1.0 kütüphanesiyle kullanımı açılmıştır.

Coroutine, sadece Kotlin dilinde kullanılmaktadır. Android uygulamalarda Java desteği bulunmamaktadır. ℹ️

Coroutine’nin tanıtıldığı video’yu incelemenizi öneririm: ✅

Coroutine Özellikleri 🖼

Kotlin Coroutines Features

Coroutine özelliklerinin 4 ana başlık altında toplayabiliriz.

  • Lightweight: Tek thread üzerinde birçok Coroutine çalıştırılabilir. Coroutine çalıştığı thread’i bloklamadığı için birçok defa Asynchronous işlemi destekler, bellektende tasarruf sağlayabilir.

Thread: Bir process’in birden fazla görevi aynı anda yapmasını sağlayan yapıdır.

  • Built-In Cancellation Support: Çalışmakta olan Coroutine’nin hiyerarşisi vasıtasıyla otomatik iptal desteği sunmaktadır.
  • Fewer Memory Leaks: Coroutine’in çalıştığı scope iptal edildiği zaman o scope’un sorumluluğunda olan tüm coroutine’ler iptal edilir.
  • Jetpack Integration: Birçok Jetpack kütüphanesi, Coroutine desteği sunmaktadır.

Jetpack: Android’in uygulama geliştirirken kullanılmasını önerdiği library ve tools’dan oluşan ve Android Developerların verimli, kaliteli ve hızlı çalışan uygulamalar yazabilmesini sağlayan bir yardımcı pakettir.

Android Coroutines entegrasyonu nasıl yapılır ⁉️

Coroutines’i denemek, kullanabilmek için Android projemizi açıp, build.gradle(app module)içine dependencies etiketi altına aşağıdaki kütüphaneleri eklememiz gerekiyor.

Gradle hakkında detaylı bilgi için linkteki yazıyı inceleyebilirsiniz:

Coroutine oluşturmak için hangi fonksiyonlar kullanılır 🤨

  • launch: Çalıştığı thread’i bloklamayan builder fonksiyondur. launch’u kullanabilmek için Coroutine Scope içerisinde bulunulması gerekir.
  • runBlocking: Yeni coroutine başlatmaya yarar. İlgili görev tamamlanana dek main thread bloklanır.

Örnekte runBlocking kullanımını deneyimliyoruz. delay(2000)gecikme fonksiyonudur. Daha sonra ilgili işlemlerin yapılmasına devam ediliyor.

Run Blocking-Coroutine

Kodun çıktısında öncelikle runBlocking öncesindeki println yazdırılıyor. Daha sonra 2 sn beklenip, main thread bloklanarak launch içindeki println daha sonrada dıştaki println değerleri yazdırılıyor.

GlobalScope’un runBlocking’ten farkı bağımsız hareket etmesidir. Bulunduğu thread’in bitmesi onun çalışmasına engel değildir.

GlobalScope-Coroutine

Örnekte başta println içindeki değer yazdırılır daha sonra GlobalScope dışındaki değerler, işlemler yapılır. En sonda ise launch içindeki işlemler yürütülür. Burada 2 sn bekletip, println içindeki değer yazdırılır.

CoroutineScope Nedir ❓

GlobalScope’a benzer şekilde çalışmaktadır. Bloklamadan işlemlere devam edebilir. Hangi thread üzerinde çalışma yapılacaksa o belirtilebilir.

CoroutineScope-Coroutine

Benzer şekilde üstünde ya da altındaki işlemler yapılıp daha sonra scope içindeki işlemler yapılıyor.

CoroutineScope(context) alarak kullanılabiliyor. Class içinde kullandığımız context değil. Dispatchers türündeki context elemanları kullanılmalıdır.

Coroutine Dispatchers Nedir? 🎁

Coroutine’in hangi thread’de çalışacaksa onu belirten bir mekanizmadır. 4 farklı türü bulunmaktadır.

  • Dispatchers.Default : CPU işlemlerinde kullanılır. launch , async standart coroutine oluşturma fonksiyonlarının default dispatcher’ıdır.
  • Dispatchers.IO : Network ve Disk bazlı işlerde kullanılır. Kurumsal uygulamalarda sıklıkla kullanılmaktadır.
  • Dispatchers.Main : Main Thread ile çalışır. UI thread işlemleri yapılır.
  • Dispatchers.Unconfined : Main Thread işlemlerinde kullanılmasına rağmen kullanılması pek önerilmeyen bir dispatcher’dır. Çağrılan thread’de coroutine işlemini başlatır.

İşlemlerin hangi thread’de çalıştığını aşağıdaki şekilde öğrendik.

Dispatchers-Coroutine

Nested Coroutines 🔎

Coroutines iç içe kullanılabilmektedir.

runBlocking içinde delay’a bağlı olarak önce Coroutine Scope daha sonrada Run Blocking işlemlerini yapılır.

Nested Coroutines

Suspend Function 👀

Mevcut çalışan thread’i bloklamadan işlemlerin tamamlanmasına olanak sağlar. Suspend; yeniden başlatılıp, durdurulabilir fonksiyonlardır. Bu fonksiyonlar coroutine içerisinde kullanılmalıdır.

Örneğimizde 2 farklı fonksiyon tanımlayıp main() içinde çağıracağız.

  • Suspend olmayan fonksiyonlar içerisinde coroutineScope kullanılamaz.
  • Normal fonksiyonlarsuspend fonksiyonların içinde kullanılmasına rağmen bir suspend fonksiyon, normal fonksiyon içerisinde çağrılıp, kullanılamaz.

suspendFunction() runBlocking scope’u içinde sorunsuz bir şekilde çağırabiliyoruz.

Suspend Function-Coroutines

delay fonksiyonuna verilen değerlere göre ilgili işlemler işletilip, console ilgili bilgiler yazdırılıyor.

Coroutines Async 🧨

Geriye değer döndüren asenkron işlemlerde kullanılır. launch dan farkı Job yerine Deffered döndürmesidir. Sonuca ulaşabilmek için await() fonksiyonu kullanılır.

Örneğimizde suspendtipinde iki fonksiyon tanımlayıp, içlerinde sanki bir indirme yapılıyormuş gibi işlemler yapacağız.

Tanımlamış olduğumuz 2 adet suspend fonksiyonu, runBlocking içinde farklı değişkenlere await() vasıtasıyla aktarıyoruz. Bu şekilde işlemleri asenkron şekilde kolayca tamamlayabiliyoruz.

Coroutines Job 📌

Coroutine’in yaşam döngüsünü kontrol eden mekanizmadır. Job’lar başka job’lar içinde kullanılabilir. invokeOnCompletion ile Job tamamlandığı zaman yapılmak istenen işlemler belirtilir.

runBlocking içinde nested job kullandık. Job bitiminde ise console mesaj yazdırdık.

Nested Jobs-Coroutines

İşlemler sırasıyla yapılıp println() içindeki mesajlar yazdırıldı.

Job-Coroutines

firstJob.cancel() kullanıldığı zaman job içindeki işlemlere bakılmaksızın direkt invokeOnCompletion içinde ne varsa o yürütülüp, job tamamlanır.

Coroutines withContext 🔗

Coroutine, CoroutineContext türünde bir nesne içinde çalışmaktadır. API kullanımlarında sıklıkla karşımıza çıkan bir yapıdır. Bulunduğunuz dispatcher dan farklı bir dispatcher ‘a geçmek istendiğinde withContext kullanılabilir. Scope değişikliği olmadan aynı scope içinde farklı thread’lerde işlemler yapmamıza olanak sağlar.

Hangi dispatcher’da çalıştığımızı console’da rahatlıkla görüntüleyebiliyoruz.

withContext-Coroutines

Herkese keyifli 😁 okumalar 📚. Sağlıklı 🥰 günler dilerim.

Android Developer 👨🏻‍💻