async — Coroutine Builder sa Kotlin na nagpapatakbo ng coroutine at nagbabalik ng Deferred<T> na object para makuha ang resulta ng asynchronous na operasyon. Pinapayagan ng async ang parallel na pagpapatupad ng maraming gawain at pagsasama-sama ng kanilang mga resulta sa pamamagitan ng await(). Ayon sa gabay ng JetBrains, 2024, ang async ay ang mas gustong paraan ng pag-oorganisa ng parallel computations sa mga coroutine.
Mga Pangunahing Punto
async — ay isang extension function ng CoroutineScope na lumilikha ng coroutine na may pagbabalik ng resulta. Hindi tulad ng launch, ang async ay nagbabalik ng Deferred<T> — isang bagay na kumakatawan sa isang hinaharap na halaga. Ang coroutine na pinatakbo sa pamamagitan ng async ay isinasagawa nang konkurent sa iba pang mga coroutine, na nagpapahintulot ng parallelisasyon ng mga computation.
Ang async ay ginagamit kapag ang resulta ng asynchronous na operasyon ay kailangan para sa karagdagang pagproseso: pagkarga ng data mula sa maraming source, batch processing ng mga koleksyon, parallel na mga kahilingan sa iba't ibang API. Deferred ay nilikha agad, at ang resulta ay magiging available pagkatapos matapos ang coroutine.
import kotlinx.coroutines.*
suspend fun String.delayedValue(): String {
delay(1000L)
return this
}
fun main() = runBlocking {
val deferred: Deferred<String> = async { "Hello".delayedValue() }
println(deferred.await())
}
Ang syntax ng async ay katulad ng launch: parehong mga parameter na CoroutineContext, CoroutineStart at suspend-block. Ang pagkakaiba ay sa uri na ibinabalik — Deferred<T> sa halip na Job, kung saan ang T ay ang uri ng resultang ibinalik ng huling expression ng block.
public fun <T> CoroutineScope.async(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> T
): Deferred<T>
Deferred<T> — interface na nagmamana ng Job at nagdaragdag ng mga paraang await(), getCompleted(), getCompletionExceptionOrNull(). Ang await() ay isang suspend-function at maaari lamang tawagin sa loob ng coroutine o ibang suspend-function. Ang getCompleted() — ay isang non-blocking na paraan na nagtatapon ng exception kung hindi pa tapos ang coroutine.
Ang pangunahing bentahe ng async ay ang kakayahang magpatakbo ng mga gawain nang parallel. Sa halip na sunud-sunod na paghihintay sa bawat operasyon (kabuuang oras = kabuuan ng mga oras), ang async ay nagpapatakbo ng mga coroutine nang sabay-sabay, binabawasan ang kabuuang oras sa oras ng pinakamahabang operasyon.
Karaniwang senaryo — pagkarga ng profile ng user, kanyang mga setting, at kasaysayan ng order na may tatlong parallel na async na kahilingan. Pagkatapos matapos ang lahat ng tatlo, ang mga resulta ay pinagsama sa iisang modelo ng data.
suspend fun loadUserDashboard(userId: String): Dashboard = coroutineScope {
val profile = async { api.getProfile(userId) }
val settings = async { api.getSettings(userId) }
val orders = async { api.getRecentOrders(userId) }
Dashboard(
profile = profile.await(),
settings = settings.await(),
orders = orders.await()
)
}
Ang function na coroutineScope ay nagpapatakbo ng mga child coroutine at naghihintay sa kanilang pagkumpleto bago ibalik ang resulta. Ang buong block ay isinasagawa nang parallel, hindi sunud-sunod.
Sinusuportahan ng Deferred ang ilang mga paraan para sa pagtatrabaho sa resulta. Bukod sa await(), may mga paraan para sa pagsusuri ng status, pagkuha ng handa na halaga, at pagsasama-sama ng maraming Deferred sa pamamagitan ng mga utility function ng Kotlin Coroutines.
| Paraan | Paglalarawan | Suspend? |
|---|---|---|
| await() | Pinipigilan ang coroutine hanggang makuha ang resulta | Oo |
| getCompleted() | Ibinabalik ang resulta kung tapos na ang coroutine (kung hindi ay Exception) | Hindi |
| getCompletionExceptionOrNull() | Ibinabalik ang exception kapag may error o null | Hindi |
| isCompleted | Sinusuri kung tapos na ang coroutine | Hindi |
Para sa pagsasama-sama ng listahan ng Deferred ay ginagamit ang awaitAll() — isang function na pumipigil sa pagpapatupad hanggang sa matapos ang lahat ng Deferred sa koleksyon. Kung kahit isa ay natapos na may error, ang awaitAll() ay nagtatapon ng exception.
suspend fun <T> loadAll(requests: List<suspend () -> T>): List<T> {
return coroutineScope {
val deferreds = requests.map { async { it() } }
deferreds.awaitAll()
}
}
Ang pagpili sa pagitan ng async at launch ay depende sa kung kailangan ang resulta ng pagpapatupad ng coroutine. launch ay nagbabalik ng Job at angkop para sa fire-and-forget na mga operasyon, async ay nagbabalik ng Deferred at ginagamit para sa mga gawaing nagbabalik ng data. Sa mga tuntunin ng syntax at parameter, ang mga tagabuo ay magkapareho.
Mahalagang tuntunin: huwag gumamit ng async para sa fire-and-forget. Kung hindi kailangan ang resulta ng coroutine, gamitin ang launch. Ang async ay lumilikha ng overhead para sa paggawa ng Deferred, na hindi makatwiran sa ganitong senaryo.
Sa Android, ang async ay ginagamit para sa parallel na mga operasyon sa loob ng ViewModel at UseCases. Mga karaniwang senaryo: sabay-sabay na pagkarga ng profile at news feed, pagkuha ng panahon mula sa maraming serbisyo ng panahon, batch synchronization ng data sa server.
class HomeViewModel : ViewModel() {
fun loadHomeScreen() {
viewModelScope.launch {
val userData = async(Dispatchers.IO) { repository.getUserData() }
val newsFeed = async(Dispatchers.IO) { repository.getNewsFeed() }
val notifications = async(Dispatchers.IO) { repository.getNotifications() }
val state = HomeState(
user = userData.await(),
news = newsFeed.await(),
unread = notifications.await()
)
_uiState.update { state }
}
}
}
Inirerekomenda na balutin ang grupo ng async sa coroutineScope o supervisorScope para sa paghihiwalay ng error. Pinapayagan ng supervisorScope ang pagpapatuloy ng pagpapatupad ng iba pang mga async coroutine kahit na may error sa isa sa mga ito — kapaki-pakinabang para sa hindi kritikal na mga operasyon.
Mga Madalas Itanong
Maaari, ngunit walang saysay. Ang async na walang await() ay nagpapatakbo ng coroutine, ngunit ang resulta nito ay nawawala. Kung hindi kailangan ang resulta, gamitin ang launch — hindi ito lumilikha ng Deferred at mas mahusay sa memorya at pagganap.
Ang exception sa loob ng async ay nai-save sa Deferred. Ang pagtawag sa await() ay nagtatapon ng exception na ito. Para suriin nang hindi nagtatapon, gamitin ang getCompletionExceptionOrNull(). Kapag gumagamit ng coroutineScope, kinakansela ng error ang lahat ng child coroutine.
awaitAll() — isang extension function para sa Iterable<Deferred<T>> na pumipigil sa coroutine hanggang matapos ang lahat ng Deferred. Ibinabalik ang listahan ng mga resulta. Kung kahit isang Deferred ay natapos na may error, itinatapon nito ang exception at kinakansela ang iba pa.
Oo. Ang async ay isang extension function ng CoroutineScope, nakatali sa scope. GlobalScope.async ay lumilikha ng coroutine na walang koneksyon sa lifecycle — maaari itong tumakbo nang walang katapusan. Sa Android, ang GlobalScope ay hindi inirerekomenda dahil sa panganib ng pagtagas ng memorya.
Ang bilang ay idinidikta ng dispatcher: Sinusuportahan ng Dispatchers.IO ang hanggang 64 na sabay-sabay na thread, Dispatchers.Default — batay sa bilang ng CPU cores. Para sa malawakang operasyon, gumamit ng limitadong paralelismo sa pamamagitan ng Semaphore o mapNotNull na may awaitAll.
Buod
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.
Basahin din