Nedir bu Kotlin Coroutines?

Oguz Şahin
Ekmob Developer Studio

--

Asenkron programlama için kullanılan kotlin coroutines, biz android developerların işini fazlasıyla kolaylaştıran bir araç. Her android geliştiricinin yegane amacı kullanıcımıza kesintisiz ve performanslı bir akış sunmak. Bir ağ isteği attığımızda, local databaseden bir veri isteği yaptığımızda veya daha genel olarak threadde uzun sürecek bir işlem yaptığımızda imdadımıza main threadi kitlememek ve kesintisiz akışı kesmemek için coroutineler yetişiyor. Coroutinesleri threadde yapılan işlemin yapıldığı iş parçacıkları olarak düşünebiliriz.Genel olarak Lightweight Thread olarak tanımlanıyor. Bu konuda şuraya özellikle vurgu yapmak istiyorum; Threadlere benzer olmalarına rağmen coroutinesleri kullanarak yeni bir threadde iş yapmış olmuyoruz. Zaten coroutineslerin bu kadar popüler yapanda o. Çünkü yeni bir thread açmak çok maliyetli bir işlem. Out of memory hatası almamıza yol açabilir. Fakat coroutinesler threadlere göre çok daha light yapılar olduğu için daha az enerji harcayarak daha çok iş yaparlar.

Artık biraz da koda girip nasıl kullanacağamıza ve kullanılan sytanxı açıklamaya çalışalım. Öncelikle dependencylerimizi ekleyelim.

dependecies

Suspend Function

Mevcut threadi bloklamadan askıya alınma işlevini sağlarlar. Daha iyi açıklamak gerekirse yukarıdaki örnekte de görüldüğü gibi bir suspend keywordlu fonksiyon ile normal işlemler birbirini bloklamaz ve suspend keywordlu fonksiyon askıya alınarak bir coroutine içerisinde threaddeki diğer işten bağımsız asenkron bir şekilde çalıştırılabilir. Suspend Fonksiyonlar, normal bir fonksiyon yazmak gibidirler. Tek farkı sadece suspend keywordu getirilerek başlatırlar. İçerisinde coroutines çalıştırılabilen fonksiyonlardır. İstediğimiz zaman durdurup ,devam ettirip ve bitirebiliriz. Burada dikkat edilmesi gereken nokta suspend fonksiyonları ya bir suspend fonksiyon içerisinden veya coroutine içerisinden çağırabiliriz.

Örnek 1

Burada aslında diğer kavramları da içeren bir kod parçası var. Aslında topu biraz da ordan alıp devam edelim. Şimdi suspend fonksiyonların başka bir suspend fonksiyonlardan veya bir coroutineden çağrıldığını söylemiştik. Bu örnek kod parçasında da görüldüğü gibi coroutineden çağrılıyor.

Coroutine Başlatma

Yukarıdaki kod parçasında da gördüğünüz launch gibi, bir coroutine başlatmak için coroutine builder gerekli. Bunlar launch ,async veya runBlocking olabilir.

launch: CoroutineScope’ta mevcut iş parçacığını engellemeden bir coroutine başlatan coroutine builder olarak tanımlanır. Bir job objesi döndürür. Bu job objesini iptal ederek coroutinei iptal edebilrisiniz. Fire and forget mantığı ile çalışır. Genelde de bu mantıkla açıklanıyor. CoroutineScopeun extension fonksiyonudur. Bu nedenle kullanmak için bir CoroutineScope oluşturmaya ihtiyacımız vardır.

async : Aynı launch gibi async ile de coroutine başlatabiliriz.Geriye Deferred objesi döner. Bu objeyi iptal ederek coroutine iptal edebilrisiniz. Launchdan farkı bir asenkron şekilde ilerlemek için await() fonksiyonu ile cevap gelmesini bekler. Bu da size paralel işlem yapmak için olanak sağlar.

runBlocking : Yeni bir coroutine çalıştırır ve tamamlanana kadar mevcut main threadi bloklar. Genelde kullanılması önerilmez ve daha çok test için kullanılır.

Örnek 2

Burada da görüldüğü üzere gelen cevabın asenkron biçimde yazdırmış olduk.

İptal İşlemi

Bir coroutinde gerçekleşen işlemi istediğimiz zaman iptal edebiliriz. launch terimini açıklarken de geriye bir job objesi döndürdüğünü söylemiştik, bu job objesini cancel() metoduyla iptal edip o coroutinei bitirebiliriz. invokeOnCompletion ile de coroutine sonlandırıldığında yapılacak işlemi kodlayabiliriz. Genelde activity ve fragmentların onDestroy metodunda coroutine iptal edilerek hali hazırda açık kalan coroutineleri kapatabiliriz.

Coroutine Dispatchers

Coroutinelerimizi farklı threadlerde çalıştırmayı sağlar. Yapacağımız işlemin niteliğine göre dispatchersla hangi threadde olacağını belirteceğiz.

Dispatchers.Default : CPU kullanımın yoğun olduğu işlerde kullanılır.Örneğin görüntü işleme gibi ya da çok uzun bir dizinin içinden bir filtreleme yapmak gibi işlerde kullanılır.

Dispatchers.IO : Networking işlemlerinde kullanılır. Örneğin internetten bir veri çekmek veya databaseden veri almak gibi işlemlerde kullanılır.

Dispatchers.Main : UI ile ilgili yaptığımız işlemler için kullanılır. Örneğin IO’da yaptığımız bir işi mainle gösterebiliriz. İnternetten veri çekerekn IO’yu ,bu veriyi kullanıcıya UI’da gösterirken Main’i kullanabiliriz. Geçiş işleminin nasıl yapılacığını da withContex ile göreceğiz.

Suspend fonksiyon için verdiğimiz örnekte de görüleceği üzere(Örnek 1) suspend fonksiyonumuz bir internetten veri alma işi yapıyor gibi yazmıştık ve CoroutineScope’a dispatchers olarak IO belirttik. İşte o kullanım tam da buraya oturuyor. Gelin isterseniz kısa bir örnekle hangi thread üzerinde çalıştıklarını görelim.

Örnek 3

Log çıktımızdan da görüleceği üzere Dispatchersla hangi thread üzerinde işlem yapabileceğimizi kendimiz organize edebiliyoruz.

withContext

Şimdi gelelim withContext ne iş yapara. İlk örnekte de görüleceği üzere kullanımını gördük. Hatta bunu Dispatchers.Main’i açıklarken de söylemiştik az çok ne iş yaptığını. Biz Dispatchers ile hangi threadde çalışacağımızı söyledik. İşte yapılan işe göre de hangi Dispatcers öğesiyle çalışacaksak o öğeye geçmemizi sağlayan yapıdır. Örneğin İlk örnekte verdiğimiz gibi İnternetten veriyi IO’da çektik ve withContext ile Main de UI da gösterdik.

Coroutinelerle alakalı daha derinlemesine bir giriş yapmak istiyorsanız Roman Elizarov’un sunumunu inceleyebilrisiniz.

Dilimin döndüğünce coroutinesleri sizin için açıklamaya ve örneklerle kullanımı göstermeye çalıştım. İlk medium yazımın da heyecanıyla da sürç-i lisan ettiysek affola. Coroutineslerle ilgili yazı dizimi devam ettireceğim. Bu part ile temel olarak ne iş yaptıklarını ve kullanımlarını gördük. Serinin ikinci yazısında da küçük projeyle gerçek bir kullanım üzerinden anlatmaya çalışacağım. Hepinize crashsiz kodlamalar ..

--

--