Android Coroutines Neymiş Bir Bakalım
Herkese merhaba, çok request olması durumunda patlamamak için kullanabileceğimiz bir yapı olan Coroutines’i Retrofit’le birlikte kullanabilmek için burada toplanmış bulunmaktayız.
Başlamadan önce kim nedir diye baksak iyi olur sanırım.
Retrofit
Bir API ve Android uygulaması arasında bağlantı kurmak için kullanılan kütüphanelerden birisidir. Ayrıntılı anlatımı için Retrofit: Kimler Android App’inden bir API’ya bağlanmak ister? yazımı okuyabilirsiniz :)
Coroutines
Android’de main threadi bloklamadan yani asenkron olarak çalışmasını sağlamak için kullanılan bir tasarım modelidir diyebiliriz. Bunu biraz daha açarak ilerlemekte fayda var tabi ki.
Android uygulama geliştirirken performansı korumak isteriz. Eğer tüm yapıyı tek bir thread üzerine kurarsanız, o threadin omuzlarına biraz ağır gelebilir, isyan edebilir. İşte bunun için thread yönetimi yapmaya gerek kalmadan küçük iş parçacıkları kullanmamızı kolaylaştıran yapımıza Coroutines deniyor. Coroutines threadlere benzer ama thread değildir. Bu kadar kullanışlı ve popüler olmasını buna bağlayabiliriz sanırım. Yeni bir thread oluşturup bir işlem yapmak oldukça zahmetli ve maaliyetli bir iştir, memoryi doldurmanıza neden olabilir. Yani threadler ile işlem yapacaksanız thread yönetimini iyi yapmanız gerekmektedir. Fakat coroutinesler threadlere göre daha az enerji harcayarak daha çok iş yaparlar.
E bu kadar konuştuk ettik, ne olduğunu öğrendik de nasıl kullanılır hala bilmiyoruz. Ufacık bir implementasyon ile muradımıza erelim.
Öncelikle coroutines kullanmak için eklememiz gereken bir küçük dependency var.
//Coroutines
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1'
Ardından yaptığımız işlemleri Coroutines scopeları içine yazacağız ki asenkron iletişim kurabilelim. Ben birazdan Retrofit ile bağlantı kurduğum bir yapı ile göstereceğim, burada request atıldığı için işlemler arasındaki farkı daha kolay göreceğiz. Öncelikle kurduğum yapıyı özetliyorum. Retroift ile hot ve cold coffee listesi çekebileceğim endpointler buldum ve bunların yapılarını kurdum. Retrofit: Kimler Android App’inden bir API’ya bağlanmak ister? yazımdakinin aynısı yani. Sadece ek olarak sadece hot coffees değil cold coffeleri de çekebileceğim bir endpoint ekledim. Bunun harici de aldığım dataları recyclerview içine bastırdım. Onu da Android RecyclerView İçin Adapter Yazmaya Ne Dersiniz? yazımda bulabilirsiniz :) Bu ikisinin birleşiminden çıkan projeye Coroutines eklemeye geldi sıra. Şimdi en can alıcı noktayı anlatma zamanı.
MainActivity içerisinde atmış olduğum requestlerden birisi aşağıdaki gibi.
Bu cold coffees içindi, bir de aynısını hot coffees için yaptık tabi. Peki Coroutinesi nerede kullanacağız? Request attığımız bu alanı direkt bir Coroutines scope’u içerisine alırsak bir iş parçacığına atamış olacağız. O da kendi halinde takılıp gidip datalarını alıp gelecek. Aynı şekilde hot coffees için yazdığımız requesti de farklı bir Coroutines scope u içine alırsak bunlar birbirinden bağımsız paralel çalışarak gidip datalarını alıp gelecek. Tabi ben scope scope diyorum da ne bu Coroutines scopeu?
CoroutineScope(Dispatchers.Default).launch {}
İşte yukarıdaki Coroutines scopeu. Bu kısımda kullandığımız bazı Dispatcher türleri var ne olduklarını kısa bir özet geçip projemize dönüş yapacağım.
- Dispatchers.Default : CPU kullanımın yoğun olduğu (görüntü işleme veya filtreleme gibi) işlerde kullanılır.
- Dispatchers.IO : Networking işlemlerinde (internetten bir veri çekmek veya databaseden veri almak gibi)kullanılır.
- Dispatchers.Main : UI ile ilgili yaptığımız işlemler için kullanılır.
Bu kısımda internetten veri çekerken 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 yöneteceğiz. Az sonra uygulamalı örnek karşınızdayım.Mesela öncelikle farklı scopelarda yazalım. Scopeları da aşağıda göstermiş olalım hemen.
Öncelikle IO scopeunu kullanarak data çekme işlemlerimi yaptım. Bu çektiğim dataları UI’ımda göstermek istşyorum. Requesti attıktan sonraki kısmı withContext yapısını kullanarak Main iş parçacığına aktarıyorum. Böylece network kısmını IO yaparken UI kısmını Main ile yapıyoruz.
Şimdi işlemleri inceleyelim. Ben MainActivity’de önce hot sonra cold coffee listini alacak sırada yazmıştım aslında. Farklı Coroutines scopelarında yazınca ne olduğunu görelim. Her iki scopeun içine de bir log attım.
Gördüğünüz gibi sırası hot sonra cold coffees olmasına rağmen önce cold coffees gelmiş sonra hot coffes gelmiş. Tabi bu kısım değişebilir, beş farklı data alırsanız yerleri farklılaşabilir. Bu ufacık bir örnek sadece. Demek ki farklı Coroutines scopelarında yazında birbirinden bağımsız hareket edebiliyorlarmış. Peki aynı scope içinde yazarsak n’olur? Mesela aşağıdaki gibi…
Aynı scope içine yazdığım kodlar sırasıyla gerçekleşir, çünkü aynı iş parçacığını kullanırlar. Bu yüzden bu kodun çıktısı aşağıdaki gibi olacaktır.
Bir coroutines scopeunu istediğiniz zaman iptal edebilirsiniz bu arada, launch olarak açmış olduğumuz scope da bize bir job nesnesi verilir, adını spesific belirlemezseniz genelde this şeklinde alabilirsiniz. this.cancel() derseniz o coroutine iptal edilmiş olur. Benden bu kadar, yapmış olduğumuz projenin kodunu da linkte bırakıyorum ve sizleri iyice kurcalamaya davet ediyorum :D