- 15 Mar 2018
- 1,109
- 25
Kotlin #4 | Coroutine Nedir? Örneklerle
Coroutine Nedir?
Coroutine, Kotlin'de Thread'leri yönetmemizi sağlayan, belli bir rutinde çalışan işler oluşturmamıza yarayan, async, await gibi Java'da onlarca satırda kodlanan işlemleri kolaylaştırmak için JetBrain ekibi tarafından geliştirilmiş bir yapıdır. Coroutine'ler aynı zaman Android Jetpack'in de bir parçasıdır.
Kotlin'de diğer dillerin Coroutine temelinin yanı sıra suspend function gibi yapıları getirerek, daha az hata ve daha güvenli bir ortam sağlıyor.
Kotlin, Coroutine gibi yapıların kütüphanesi manuel olarak dahil edilmesini sağlamak için kendi kitaplığında minimum düzeyde API bulundurur. Bu yüzden kullanmak istediğimizde 'kotlinx.coroutines' kütüphanesini aktif etmemiz gerekir.
Android Studio için Coroutine'i projemize dahil edelim.
build.gradle (app) dosyamızın içinde dependencies'in altına bunları ekleyelim
Daha sonra kütüphane değişikliğimizin geçerli olması için Sync Now diyelim
İlk kodlarımızı yazmaya başlamadan önce bazı kavramları öğrenmemiz gerek.
1- Scope Nedir?
Scope, Türkçe anlamıyla alan, faaliyet alanı; Tam olarak programlamadaki anlamıyla eştir. Scope bir kodun çalıştığı alanı temsil eder. Scope seçimini düzgün yapmak önemlidir çünkü her zaman her yerde farklı scope'ları kullanmak gerekebilir.
Biz bir coroutine çalıştırdığımızda ve scope belirtmediğimizde kodu otomatik olarak Coroutine Scope'da çalıştırır. Coroutine Scope Nedir?
Coroutine Scope yeni coroutine için bir scope olarak tanımlanır coroutine'lerin default scope'udur. 'launch', 'run blocking' gibi kavramlar Coroutine Scope'a dahildir.
Global Scope ise bütün uygulamada çalışan üst level Coroutine scope'udur. Coroutine Scope'un aksine bütün yaşamdöngüsü boyunca çalışırlar.
Gördüğünüz gibi GlobalScope'da bir işlem çalıştırdık 100.000 defa a"ndroid" yazdırdık. Bu örnekte de gördüğünüz üzere launch'un içinde launch çalıştırabiliyoruz.
Gördüğünüz üzere Coroutine Scope ise bütün uygulamada çalışmadığı sadece belirtilen thread'de çalıştığı için tanımlanırken coroutine context belirtmemiz gerekiyor, burada "Dispatchers.Default", çalıştırılan kod güncel olarak hangi thread'deyse orada çalıştırılması manasına geliyor.
Burada yine delay kodunu kullandık delay gecikme demek burada değeri bizden milisaniye olarak alıyor o kadar süre bekliyor ve ondan sonra işlemi yapıyor.
Run Blocking Nedir?
Run Blocking güncel olan işlemleri durdurma, run blocking süresi dolana kadar ve içindeki işlem tamamlanana kadar hiçbir şey yapmama manasına geliyor. Gelin runblocking nasıl kullanılıyor ona bakalım
Şimdi diyebilirsiniz Run Blocking işlemine ne gerek var zaten delay ile geciktirebiliyorduk bunu ne zaman kullanalım? İşte şimdi Run Blocking'i ne zaman kullanmamız gerektiğini göreceğiz. Örneğimize bakalım
Thread & Coroutine Context Nedir?
Yukarıda da kısaca değinmiş olduğum üzere; Coroutine Context, Coroutine'in hangi thread'de işlem göreceğini belirtir
Gördüğünüz gibi launch'tan sonra thread belirtirsek Thread.currentThread() bize hangi thread'de olduğumuzu yansıtıyor. Bunun çıktısını görelim
Gördüğünüz gibi default, io ve unconfined thread'lerin hepsi farklı dispatcher'larda çalışıyor. Tanımlamadığımız zaman ise otomatik olarak main thread'e atıyor.
Peki neden farklı Coroutine Context'leri kullanma ihtiyacı duyalım?
Farklı Coroutine Context'leri genellikle internetten bir aracı kütüphane olmadan indirirken kullanırız. Veriler I/O'da alınır böylece main thread bloklanmadan veri alınır daha sonra ise main'de işlenir.
Şimdi detaylı örneğimizi görmeden önce öğrenmemiz gerek birkaç kavram daha var onlar da Suspend Function ve Job Kavramları
Job Nedir?
Job, Türkçe anlamıyla iş; Kotlin'deki anlamına benziyor, Coroutine'i nasıl launch şeklinde çağırıyorsak burada da aynı şekilde fakat Job, Coroutine işlerinin değişken halidir. Ne demek istiyorum, bir örnekle görelim
Gördüğünüz gibi daha önceki Kotlin derslerinde gördüğümüz gibi val olarak tanımlayabiliyoruz. invokeOnCompletion metodu ile Job bittiğinde ne olacak onu söylüyoruz. Ve Job'u cancel yani iptal edebiliyoruz. İşte bunlar job tanımanın güzellikleri.
Suspend Function Nedir?
Suspend Function basitçe, istediğimiz zaman durdurup başlatabildiğimiz fonksiyonlara denir. Uzun süreli işlemlerde uygulamayı bloklamadan yapacağımız işlemler için kullanılır. Suspend Function sadece Coroutine içinde çağrılabilir.
Gördüğünüz gibi bir örnek kullanımı bu şekildedir.
Son olarak değinmemiz gereken bir kavram; Async
Async Nedir?
Async; asynchronous, Türkçe anlamıyla; asenkron, senkronize olmayan. Async işlemler main thread'i bloklayıp uygulamayı çökertmek istemediğimiz zaman kullandığımız kavramdır. Async işlemlerde bütün işlemler uygulamada olmaya devam ederken async altında belirtilen işlemlerde uygulamadaki işlemlerden bağımsız olmaya devam eder
Şimdi Coroutine'lerle ilgili öğrenmemiz gereken her şeyi öğrendik, şimdi hepsini kullandığımız bir örnek yapalım.
Öncelikle downloadNameData() ve downloadAgeData() isimli iki suspend fonksiyon oluşturduk. İki fonksiyonun içinde de bir süre beklettik değeri verdik ".. download" yazdırdık ve verdiğimiz değeri döndürdük. Normal bir internetten veri çekme işlemi daha uzun süreceği için bu işlemi thread'i bloklayan ve I/O'yu kullanan işlemler gibi düşünelim.
Gördüğünüz gibi downloadName ve downloadAge isimli async işlemler oluşturduk ve içinde internetten(!) verilerimizi çektik, unutmayın bunlar uygulamanın zaman akışından bağımsız.
Daha sonra kendi değerlerimizle indirdiğimiz değerleri eşleştirdik ama farketmişsinizdir burada .await() kullandık. await'i kullanmamızın sebebi async olduğu için ve zaman akışına göre ilerlemediği için biz o kod satırındayken o değer aslında geldi mi gelmedi mi bilmiyoruz await ise değer geldiği zaman eşitliyor ve bizi null değerlerden koruyor
Eğer içerik ile ilgili herhangi bir sorunuz varsa öm, ya da buradan sorabilirsiniz elimden geldiğince cevaplamaya çalışırım. İyi forumlar )
Coroutine Nedir?
Coroutine, Kotlin'de Thread'leri yönetmemizi sağlayan, belli bir rutinde çalışan işler oluşturmamıza yarayan, async, await gibi Java'da onlarca satırda kodlanan işlemleri kolaylaştırmak için JetBrain ekibi tarafından geliştirilmiş bir yapıdır. Coroutine'ler aynı zaman Android Jetpack'in de bir parçasıdır.
Kotlin'de diğer dillerin Coroutine temelinin yanı sıra suspend function gibi yapıları getirerek, daha az hata ve daha güvenli bir ortam sağlıyor.
Kotlin, Coroutine gibi yapıların kütüphanesi manuel olarak dahil edilmesini sağlamak için kendi kitaplığında minimum düzeyde API bulundurur. Bu yüzden kullanmak istediğimizde 'kotlinx.coroutines' kütüphanesini aktif etmemiz gerekir.
Android Studio için Coroutine'i projemize dahil edelim.
build.gradle (app) dosyamızın içinde dependencies'in altına bunları ekleyelim
dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
}
Daha sonra kütüphane değişikliğimizin geçerli olması için Sync Now diyelim
İlk kodlarımızı yazmaya başlamadan önce bazı kavramları öğrenmemiz gerek.
1- Scope Nedir?
Scope, Türkçe anlamıyla alan, faaliyet alanı; Tam olarak programlamadaki anlamıyla eştir. Scope bir kodun çalıştığı alanı temsil eder. Scope seçimini düzgün yapmak önemlidir çünkü her zaman her yerde farklı scope'ları kullanmak gerekebilir.
Biz bir coroutine çalıştırdığımızda ve scope belirtmediğimizde kodu otomatik olarak Coroutine Scope'da çalıştırır. Coroutine Scope Nedir?
Coroutine Scope yeni coroutine için bir scope olarak tanımlanır coroutine'lerin default scope'udur. 'launch', 'run blocking' gibi kavramlar Coroutine Scope'a dahildir.
Global Scope ise bütün uygulamada çalışan üst level Coroutine scope'udur. Coroutine Scope'un aksine bütün yaşamdöngüsü boyunca çalışırlar.
Gördüğünüz gibi GlobalScope'da bir işlem çalıştırdık 100.000 defa a"ndroid" yazdırdık. Bu örnekte de gördüğünüz üzere launch'un içinde launch çalıştırabiliyoruz.
Gördüğünüz üzere Coroutine Scope ise bütün uygulamada çalışmadığı sadece belirtilen thread'de çalıştığı için tanımlanırken coroutine context belirtmemiz gerekiyor, burada "Dispatchers.Default", çalıştırılan kod güncel olarak hangi thread'deyse orada çalıştırılması manasına geliyor.
Burada yine delay kodunu kullandık delay gecikme demek burada değeri bizden milisaniye olarak alıyor o kadar süre bekliyor ve ondan sonra işlemi yapıyor.
Run Blocking Nedir?
Run Blocking güncel olan işlemleri durdurma, run blocking süresi dolana kadar ve içindeki işlem tamamlanana kadar hiçbir şey yapmama manasına geliyor. Gelin runblocking nasıl kullanılıyor ona bakalım
Şimdi diyebilirsiniz Run Blocking işlemine ne gerek var zaten delay ile geciktirebiliyorduk bunu ne zaman kullanalım? İşte şimdi Run Blocking'i ne zaman kullanmamız gerektiğini göreceğiz. Örneğimize bakalım
Thread & Coroutine Context Nedir?
Yukarıda da kısaca değinmiş olduğum üzere; Coroutine Context, Coroutine'in hangi thread'de işlem göreceğini belirtir
Gördüğünüz gibi launch'tan sonra thread belirtirsek Thread.currentThread() bize hangi thread'de olduğumuzu yansıtıyor. Bunun çıktısını görelim
2020-10-13 09:04:06.426 6646-6677/com.ego1st.coroutinekotlin I/System.out: Default Thread: DefaultDispatcher-worker-1
2020-10-13 09:04:06.427 6646-6678/com.ego1st.coroutinekotlin I/System.out: IO Thread: DefaultDispatcher-worker-2
2020-10-13 09:04:06.427 6646-6646/com.ego1st.coroutinekotlin I/System.out: Unconfined Thread: main
Gördüğünüz gibi default, io ve unconfined thread'lerin hepsi farklı dispatcher'larda çalışıyor. Tanımlamadığımız zaman ise otomatik olarak main thread'e atıyor.
Peki neden farklı Coroutine Context'leri kullanma ihtiyacı duyalım?
Farklı Coroutine Context'leri genellikle internetten bir aracı kütüphane olmadan indirirken kullanırız. Veriler I/O'da alınır böylece main thread bloklanmadan veri alınır daha sonra ise main'de işlenir.
Şimdi detaylı örneğimizi görmeden önce öğrenmemiz gerek birkaç kavram daha var onlar da Suspend Function ve Job Kavramları
Job Nedir?
Job, Türkçe anlamıyla iş; Kotlin'deki anlamına benziyor, Coroutine'i nasıl launch şeklinde çağırıyorsak burada da aynı şekilde fakat Job, Coroutine işlerinin değişken halidir. Ne demek istiyorum, bir örnekle görelim
Gördüğünüz gibi daha önceki Kotlin derslerinde gördüğümüz gibi val olarak tanımlayabiliyoruz. invokeOnCompletion metodu ile Job bittiğinde ne olacak onu söylüyoruz. Ve Job'u cancel yani iptal edebiliyoruz. İşte bunlar job tanımanın güzellikleri.
Suspend Function Nedir?
Suspend Function basitçe, istediğimiz zaman durdurup başlatabildiğimiz fonksiyonlara denir. Uzun süreli işlemlerde uygulamayı bloklamadan yapacağımız işlemler için kullanılır. Suspend Function sadece Coroutine içinde çağrılabilir.
Gördüğünüz gibi bir örnek kullanımı bu şekildedir.
Son olarak değinmemiz gereken bir kavram; Async
Async Nedir?
Async; asynchronous, Türkçe anlamıyla; asenkron, senkronize olmayan. Async işlemler main thread'i bloklayıp uygulamayı çökertmek istemediğimiz zaman kullandığımız kavramdır. Async işlemlerde bütün işlemler uygulamada olmaya devam ederken async altında belirtilen işlemlerde uygulamadaki işlemlerden bağımsız olmaya devam eder
Şimdi Coroutine'lerle ilgili öğrenmemiz gereken her şeyi öğrendik, şimdi hepsini kullandığımız bir örnek yapalım.
Öncelikle downloadNameData() ve downloadAgeData() isimli iki suspend fonksiyon oluşturduk. İki fonksiyonun içinde de bir süre beklettik değeri verdik ".. download" yazdırdık ve verdiğimiz değeri döndürdük. Normal bir internetten veri çekme işlemi daha uzun süreceği için bu işlemi thread'i bloklayan ve I/O'yu kullanan işlemler gibi düşünelim.
Gördüğünüz gibi downloadName ve downloadAge isimli async işlemler oluşturduk ve içinde internetten(!) verilerimizi çektik, unutmayın bunlar uygulamanın zaman akışından bağımsız.
Daha sonra kendi değerlerimizle indirdiğimiz değerleri eşleştirdik ama farketmişsinizdir burada .await() kullandık. await'i kullanmamızın sebebi async olduğu için ve zaman akışına göre ilerlemediği için biz o kod satırındayken o değer aslında geldi mi gelmedi mi bilmiyoruz await ise değer geldiği zaman eşitliyor ve bizi null değerlerden koruyor
Eğer içerik ile ilgili herhangi bir sorunuz varsa öm, ya da buradan sorabilirsiniz elimden geldiğince cevaplamaya çalışırım. İyi forumlar )