Kotlin eş yordamları kolay bir zaman çizelgesi kullanan net, basitleştirilmiş Ağ çağrıları gibi uzun süreli görevleri yönetirken uygulamanız hızlı yanıt veriyor veya disk işlemleri için de geçerlidir.
Bu konuda, Android'deki eş yordamlara ayrıntılı bir bakış sunulmaktadır. Eğer eş yordamlar hakkında bilginiz yoksa, Bu konuyu okumadan önce Android'de Kotlin eş yordamları başlıklı makaleyi okuyun.
Uzun süreli görevleri yönetin
Eş yordamlar, işlenecek iki işlem eklenerek normal fonksiyonlar üzerine kurulur
uzun süre devam eden görevlerdir. invoke (veya call) ve return ek olarak
eş yordamlar suspend ve resume değerlerini ekler:
suspend, geçerli eş yordamın yürütülmesini duraklatarak tüm yerel verileri kaydeder değişkenlerine karşılık gelir.resume, ilgili yerden askıya alınmış bir eş yordamın yürütülmesine devam ediyor askıya alınır.
suspend işlevlerini yalnızca diğer suspend işlevlerinden çağırabilir veya
yeni bir eş yordam başlatmak için launch gibi bir eş yordam oluşturucu kullanarak.
Aşağıdaki örnekte bir uzun süren varsayıma dayalı bir görev:
suspend fun fetchDocs() { // Dispatchers.Main
val result = get("https://developer.android.com") // Dispatchers.IO for `get`
show(result) // Dispatchers.Main
}
suspend fun get(url: String) = withContext(Dispatchers.IO) { /* ... */ }
Bu örnekte, get() ana iş parçacığında çalışmaya devam eder ancak
koordinasyonunu gerektirir. Ağ isteği
işlemi tamamlandığında get, geri çağırma yerine askıya alınmış eş yordamı devam ettirir
ileti dizisine bildirim gönderilir.
Kotlin, hangi işlevin birlikte çalıştığını yönetmek için bir yığın çerçevesi kullanır kullanabilirsiniz. Bir eş yordamı askıya alırken geçerli yığın kare kopyalanıp daha sonra kullanılmak üzere kaydedilir. Devam ettirildiğinde yığın çerçevesi kaydedildiği yerden geri kopyalanır ve işlev yeniden çalışmaya başlar. Kod, sıradan bir sıralı engelleme gibi görünse de eş yordam, ağ isteğinin engellenmemesini sağladığından takip edebilirsiniz.
Ana güvenlik için eş yordamlar kullan
Kotlin eş yordamları, hangi iş parçacıklarının kullanıldığını belirlemek için görev dağıtıcılarını kullanır eş yordam yürütme. Ana iş parçacığının dışında kod çalıştırmak için Kotlin'e Varsayılan veya IO sevk görevlisinde çalışmak için eş yordamlardan birini kullanın. İçinde Kotlin, tüm eş yordamlar bir görev dağıtıcıda takip edebilirsiniz. Eş yordamlar kendilerini askıya alabilir ve sevk görevlisi devam ettirmekten sorumludur.
Kotlin, eş yordamların nerede çalıştırılması gerektiğini belirtmek için üç görev dağıtıcı sağlar. şunları kullanabilirsiniz:
- Sispatchers.Main - Ana hat üzerinde bir eş yordam çalıştırmak için bu görev dağıtıcıyı kullanın
Android iş parçacığı. Bu, yalnızca kullanıcı arayüzüyle etkileşimde bulunmak ve
yardımcı olan
ekip çalışmasıdır. Örnek olarak
suspendişlevlerini çağırma, Android kullanıcı arayüzü çerçeve işlemleri ve güncellemeLiveDatanesne. - Dispatchers.IO - Bu görev dağıtıcı, disk veya ağ gerçekleştirmek için optimize edilmiştir Ana iş parçacığının dışında G/Ç. Örnek olarak, Oda bileşeni, dosyalardan okuma veya dosyalara yazma ve ağ işlemlerini çalıştırma.
- Dispatchers.Default - Bu sevk görevlisi şu amaçlar için optimize edilmiştir: Ana iş parçacığının dışında CPU'yu yoğun şekilde kullanan iş. Örnek kullanım alanları arasında JSON'u listelemek ve ayrıştırmaktır.
Önceki örnekten devam edersek, görevleri yeniden tanımlamak için sevk görevlilerini
get işlevi. get gövdesinin içinde withContext(Dispatchers.IO) öğesini şunun için çağırın:
KS iş parçacığı havuzunda çalışan bir blok oluşturun. Bunun içine yerleştirdiğiniz
bloku her zaman IO sevk görevlisi aracılığıyla yürütülür. withContext kendisinin bir
askıya alma işlevi için, get işlevi de bir askıya alma işlevidir.
suspend fun fetchDocs() { // Dispatchers.Main
val result = get("developer.android.com") // Dispatchers.Main
show(result) // Dispatchers.Main
}
suspend fun get(url: String) = // Dispatchers.Main
withContext(Dispatchers.IO) { // Dispatchers.IO (main-safety block)
/* perform network IO here */ // Dispatchers.IO (main-safety block)
} // Dispatchers.Main
}
Eş yordamlar sayesinde, ileti dizilerini ayrıntılı denetimle gönderebilirsiniz. Çünkü
withContext(), herhangi bir kod satırının iş parçacığı havuzunu
kullanıma sunduk. Bunları, okuma gibi çok küçük işlevlere
ağ isteği gerçekleştirir.
Her işlevin ana güvenli olduğundan emin olmak için withContext(). Bu,
ana iş parçacığından işlevi çağırabilir. Böylece, arayan kişinin
işlevi yürütmek için hangi iş parçacığının kullanılması gerektiğini düşünün.
Yukarıdaki örnekte, fetchDocs() ana iş parçacığında yürütülür; ancak
Arka planda ağ isteği gerçekleştiren get numaralı telefonu güvenli bir şekilde çağırabilir.
Eş yordamlar suspend ve resume, yani ana sayfadaki eş yordamı desteklediği için
withContext bloğu olduğu anda ileti dizisi get sonucuyla devam ettirilir
tamamlandı.
withContext() performansı
withContext()
geri çağırmaya dayalı eşdeğer bir modele kıyasla fazladan
hakkında bilgi edindiniz. Dahası, withContext() çağrılarını optimize etmek mümkündür
bazı durumlarda geri çağırmaya dayalı eşdeğer bir uygulamanın ötesine geçer. Örneğin,
Örneğin, bir işlev bir ağa on çağrıda bulunursa, Kotlin'e
Bir dış withContext() kullanarak ileti dizilerini yalnızca bir kez değiştirin. Sonra,
ağ kitaplığı withContext() öğesini birden çok kez kullandığı halde aynı kalır
ileti dizileri arasında geçiş yapmaktan kaçınır. Bunun yanı sıra Kotlin, dönüşüm hunisinin
İleti dizisi değiştirmelerini önlemek için Dispatchers.Default ile Dispatchers.IO arasında
kullanmanızı öneririz.
Eş yordam başlat
Eş yordamları iki şekilde başlatabilirsiniz:
launchyeni bir eş yordam başlatır ve sonucu arayana döndürmez. Herhangi biri kabul edilen bir iş iselaunchkullanılarak başlatılabilir.asyncyeni bir eş yordam başlatır ve askıya alınmış bir sonuç döndürmenizi sağlar işlevi (await) kullanır.
Genellikle, normal bir işlevden yeni bir eş yordam launch
gibi bir normal fonksiyon await yöntemini çağıramaz. async öğesini yalnızca içerideyken kullanın
başka bir eş yordamda veya askıya alma işlevi içindeyken
yardımcı olur.
Paralel ayrıştırma
suspend işlevi içinde başlatılan tüm eş yordamlar
bu işlevin döndürüldüğünden, muhtemelen bu eş yordamların
geri dönmeden önce bitirin. Kotlin'deki yapılandırılmış eşzamanlılık ile,
bir veya daha fazla eş yordam başlatan bir coroutineScope. Ardından await() ile
(tek bir eş yordam için) veya awaitAll() (birden çok eş yordam için) için
bu eş yordamların işlevden dönmeden önce tamamlanmasını garanti eder.
Örnek olarak, iki doküman getiren bir coroutineScope tanımlayalım.
eşzamansız olarak ayarlayabilirsiniz. Her ertelenmiş referans için await() numaralı telefonu arayarak şunları garanti ederiz:
her iki async işleminin de bir değer döndürmeden önce bitmesini sağlar:
suspend fun fetchTwoDocs() =
coroutineScope {
val deferredOne = async { fetchDoc(1) }
val deferredTwo = async { fetchDoc(2) }
deferredOne.await()
deferredTwo.await()
}
Aşağıdaki örnekte gösterildiği gibi, awaitAll() öğesini koleksiyonlarda da kullanabilirsiniz:
suspend fun fetchTwoDocs() = // called on any Dispatcher (any thread, possibly Main)
coroutineScope {
val deferreds = listOf( // fetch two docs at the same time
async { fetchDoc(1) }, // async returns a result for the first doc
async { fetchDoc(2) } // async returns a result for the second doc
)
deferreds.awaitAll() // use awaitAll to wait for both network requests
}
fetchTwoDocs(), async ile yeni eş yordamlar kullanıma sunsa da işlev
önce, başlatılan eş yordamların tamamlanmasını beklemek için awaitAll() kullanıyor
geri dönüyor. Ancak, awaitAll() adlı kullanıcıyı çağırmamış olsak bile,
coroutineScope derleyici,
tüm yeni eş yordamlar tamamlanana kadar fetchTwoDocs.
Ayrıca, coroutineScope, eş yordamların gönderdiği istisnaları da yakalar
arayana yönlendirir.
Paralel ayrıştırma hakkında daha fazla bilgi için bkz. Askıya alma işlevleri oluşturma.
Eş yordam kavramları
Eş yordam
CoroutineScope
launch veya async kullanarak oluşturduğu eş yordamları takip eder. İlgili içeriği oluşturmak için kullanılan
devam eden işler (ör. çalışan eş yordamlar)
scope.cancel(). Android'de, bazı KTX kitaplıkları
belirli yaşam döngüsü sınıfları için kendi CoroutineScope kullanıyor. Örneğin,
ViewModel bir
viewModelScope,
ve Lifecycle için lifecycleScope kullanılıyor.
Ancak CoroutineScope, bir sevk görevlisinden farklı olarak eş yordamları çalıştırmaz.
viewModelScope, şurada bulunan örneklerde de kullanılır:
Android'de eş yordamlarla arka plan ileti dizisi oluşturma.
Ancak, CoroutineScope
eş yordamların yaşam döngüsünü takip etmek için
şu şekilde:
class ExampleClass {
// Job and Dispatcher are combined into a CoroutineContext which
// will be discussed shortly
val scope = CoroutineScope(Job() + Dispatchers.Main)
fun exampleMethod() {
// Starts a new coroutine within the scope
scope.launch {
// New coroutine that can call suspend functions
fetchDocs()
}
}
fun cleanUp() {
// Cancel the scope to cancel ongoing coroutines work
scope.cancel()
}
}
İptal edilen bir kapsam daha fazla eş yordam oluşturamaz. Dolayısıyla,
scope.cancel() öğesini yalnızca yaşam döngüsünü kontrol eden sınıf olduğunda çağır
imha ediliyor. viewModelScope kullanılırken
ViewModel sınıfı şunu iptal eder:
kapsamını ViewModel'in onCleared() yönteminde otomatik olarak uygular.
İş
Job
eş yordamın herkese açık kullanıcı adı. launch ile oluşturduğunuz her eş yordam
veya async,Job
eş yordamını bozar ve yaşam döngüsünü yönetir. Ayrıca, şuraya Job aktarabilirsiniz:
Aşağıdaki gösterildiği gibi yaşam döngüsünü daha da yönetmek için CoroutineScope
örnek:
class ExampleClass {
...
fun exampleMethod() {
// Handle to the coroutine, you can control its lifecycle
val job = scope.launch {
// New coroutine
}
if (...) {
// Cancel the coroutine started above, this doesn't affect the scope
// this coroutine was launched in
job.cancel()
}
}
}
Eş yordam
CoroutineContext
aşağıdaki öğe kümesini kullanarak bir eş yordamın davranışını tanımlar:
Job: Eş yordamın yaşam döngüsünü kontrol eder.CoroutineDispatcher: Gönderimler, uygun iş parçacığına çalışır.CoroutineName: Eş yordamın adı; hata ayıklama için kullanışlıdır.CoroutineExceptionHandler: Yakalanmayan istisnaları yönetir.
Bir kapsam içinde oluşturulan yeni eş yordamlar için yeni bir Job örneği
koordine ve diğer CoroutineContext öğelerine atandı
öğeleri kapsayıcı kapsamdan devralınır. Devralınan
launch veya async öğesine yeni bir CoroutineContext ileterek öğeleri
işlevini kullanın. launch veya async öğesine Job iletmenin herhangi bir etkisi olmadığını unutmayın.
yeni bir Job örneği olarak her zaman yeni bir eş yordama atanır.
class ExampleClass {
val scope = CoroutineScope(Job() + Dispatchers.Main)
fun exampleMethod() {
// Starts a new coroutine on Dispatchers.Main as it's the scope's default
val job1 = scope.launch {
// New coroutine with CoroutineName = "coroutine" (default)
}
// Starts a new coroutine on Dispatchers.Default
val job2 = scope.launch(Dispatchers.Default + CoroutineName("BackgroundCoroutine")) {
// New coroutine with CoroutineName = "BackgroundCoroutine" (overridden)
}
}
}
Ek eş yordam kaynakları
Diğer eş yordam kaynakları için aşağıdaki bağlantılara bakın: