๐ก ์ฝ๋ฃจํด์ ์๋ช ์ฃผ๊ธฐ๋ฅผ ์ ์ดํ๋ ๋ฐ ๋์์ ์ฃผ๋ ์ฝ๋ฃจํด ์ค์ฝํ ํจ์์ ๋ํ์ฌ ํ์ตํ์์ต๋๋ค.
์ฝ๋ฃจํด ์ค์ฝํ
์ฝ๋ฃจํด ์ค์ฝํ์ ํ์์ฑ
- ์๋ ์์
์ ์ค๋จ ํจ์์์ ์ค๋จ ํจ์๋ฅผ ํธ์ถํ๋ฉฐ, ์์
์ด ๋์์ ์งํ๋์ง ์๋๋ค๋ ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
- ํ๋์ ์ค๋ํฌ์ธํธ์์ ๋ฐ์ดํฐ๋ฅผ ์ป๋ ๋ฐ 1์ด์ฉ ๊ฑธ๋ฆฌ๋ฏ๋ก ์ด 2์ด ์๋ชจ
suspend fun getUserProfile() : UserProfileData {
val user = getUserData() // 1์ด ํ
val notifications = getNotifications() // 1์ด ํ
return UserProfileData(
user = user,
notifications = notifications,
)
}
- ๋ ์ค๋จ ํจ์๋ฅผ ๋์์ ์คํํ๋ ค๋ฉด ๊ฐ ํจ์๋ฅผ async๋ก ๋ํํด์ผ ํฉ๋๋ค.
- ํ์ง๋ง async๋ ์ค์ฝํ๋ฅผ ํ์๋ก ํ๋ฉฐ GlobalScope๋ฅผ ์ฌ์ฉํ๋ ๊ฑด ์ข์ ๋ฐฉ๋ฒ์ด ์๋ ์ ์์ต๋๋ค.
- ์ด๋ EmptyCorotineContext๋ฅผ ๊ฐ์ง ์ค์ฝํ์ผ ๋ฟ์ด๋ฉฐ, async๋ฅผ ํธ์ถํ๋ฉด ๋ถ๋ชจ ์ฝ๋ฃจํด๊ณผ ์๋ฌด๋ฐ ๊ด๊ณ๊ฐ ์์ต๋๋ค.
async์ ๋จ์
- ์ทจ์๊ฐ ์ด๋ ค์
- ๋ถ๋ชจ๊ฐ ์ทจ์๋์ด๋ async ๋ด๋ถ์ ํจ์๊ฐ ์คํ ์ค์ธ ์ํ๊ฐ ๋๋ฏ๋ก ์์ ์ด ๋๋ ๋๊น์ง ์์์ด ๋ญ๋น๋ฉ๋๋ค.
- ๋ถ๋ชจ๋ก๋ถํฐ ์ค์ฝํ๋ฅผ ์์๋ฐ์ง ์์
- ํญ์ ๊ธฐ๋ณธ ๋์คํจ์ฒ์์ ์คํ๋๋ฉฐ, ๋ถ๋ชจ์ ์ปจํ ์คํธ๋ฅผ ์ ๊ฒฝ์ฐ์ง ์์ต๋๋ค.
- ์ด๋ ๋ฉ๋ชจ๋ฆฌ ๋์๊ฐ ๋ฐ์ํ ์ ์์ผ๋ฉฐ CPU๋ฅผ ๋ญ๋นํฉ๋๋ค.
- ์ฝ๋ฃจํด์ ๋จ์ ํ ์คํธํ๋ ๋๊ตฌ๊ฐ ์๋ํ์ง ์์ ํจ์๋ฅผ ํ ์คํธํ๊ธฐ ์ด๋ ต์ต๋๋ค.
- cancel ๋ฉ์๋๋ฅผ ์ฌ์ฉํด ์ค์ฝํ๋ฅผ ์ทจ์ํ๋ ๋ฑ์ ๋ฐฉ๋ฒ์ผ๋ก ์กฐ์์ด ๊ฐ๋ฅํ์ง๋ง, ๋ค๋ฃจ๊ธฐ ์ด๋ ค์ฐ๋ฉด์ ์ ์ฌ์ ์ผ๋ก ์ํํ ์ ์์ต๋๋ค.
coroutineScope
- coroutineScope๋ ์ค์ฝํ๋ฅผ ์์ํ๋ ์ค๋จ ํจ์์ด๋ฉฐ, ์ธ์๋ก ๋ค์ด์จ ํจ์๊ฐ ์์ฑํ ๊ฐ์ ๋ฐํํฉ๋๋ค.
suspend fun <R> coroutineScope(
block: suspend CoroutineScope.() -> R
): R
- async๋ launch์ ๋ค๋ฅด๊ฒ coroutineScope์ ๋ณธ์ฒด๋ ๋ฆฌ์๋ฒ ์์ด ๊ณง๋ฐ๋ก ํธ์ถ๋ฉ๋๋ค.
- coroutineScope๋ ์๋ก์ด ์ฝ๋ฃจํด์ ์์ฑํ์ง๋ง ์๋ก์ด ์ฝ๋ฃจํด์ด ๋๋ ๋๊น์ง coroutineScope๋ฅผ ํธ์ถํ ์ฝ๋ฃจํด์ ์ค๋จํ๊ธฐ ๋๋ฌธ์, ํธ์ถํ ์ฝ๋ฃจํด์ด ์์ ์ ๋์์ ์์ํ์ง๋ ์์ต๋๋ค.
fun main() = runBlocking {
coroutineScope {
delay(1000)
print(10)
}
coroutineScope {
delay(1000)
prlint(20)
}
}
// 1์ด ํ
// 10
// 1์ด ํ
// 20
coroutineScope์ ํน์ง
- ์ ์ฝ๋์์ ์์ฑ๋ ์ค์ฝํ๋ ๋ฐ๊นฅ์ ์ค์ฝํ์์ coroutineContext๋ฅผ ์์๋ฐ์ง๋ง ์ปจํ
์คํธ์ Job์ ์ค๋ฒ๋ผ์ด๋ฉํ์ฌ ๋ถ๋ชจ์ ์ฑ
์์ ์ด์ด๋ฐ์ต๋๋ค.
- ๋ถ๋ชจ๋ก๋ถํฐ ์ปจํ ์คํธ ์์
- ์์ ์ ์์ ์ด ๋๋ด๊ธฐ ์ ๊น์ง ๋ชจ๋ ์์์ ๊ธฐ๋ค๋ฆผ
- ๋ถ๋ชจ๊ฐ ์ทจ์๋๋ฉด ์์๋ค ๋ชจ๋ ์ทจ์
- ์๋์ ๊ฐ์ coroutineScope ํจ์๊ฐ ์๋ค๊ณ ๊ฐ์ ํฉ๋๋ค.
suspend fun longTask() = coroutineScope {
launch {
delay(1000)
val name = coroutineContext[CoroutineName]?.name
println("[$name] Finished task 1")
}
launch {
delay(2000)
val name = coroutineContext[CoroutineName]?.name
println("[$name] Finished task 2")
}}
- ๋ชจ๋ ์์์ ๊ธฐ๋ค๋ฆฌ๋ ํน์ฑ
fun main() = runBlocking(CoroutineName("Parent")) {
println("Before")
longTask()
println("After")
}
// Before
// 1์ด ํ
// [Parent] Finished task 1
// 1์ด ํ
// [Parent] Finished task 2
// After
- ๋ถ๋ชจ๊ฐ ์ทจ์๋๋ฉด ์์๋ค ๋ชจ๋ ์ทจ์๋๋ ํน์ฑ
fun main(): Unit = runBlocking {
val job = launch(CoroutineName("Parent")) {
longTask()
}
delay(1500)
job.cancel()
}
// [Parent] Finished task 1
coroutineScope์ ์์ธ์ฒ๋ฆฌ
- ์ฝ๋ฃจํด ๋น๋์ ๋ฌ๋ฆฌ coroutineScope๋ ์ค์ฝํ์ ์ํ ์์์์ ์์ธ๊ฐ ๋ฐ์ํ๋ฉด ๋ค๋ฅธ ๋ชจ๋ ์์์ด ์ทจ์๋๊ณ ์์ธ๊ฐ ๋ค์ ๋์ ธ์ง๋๋ค.
- ์ด๋ฅผ ๊ตฌ์กฐ์ ๋์์ฑ์ ๋ณด์ฅํ๋ค๊ณ ํฉ๋๋ค.
- ์ฝ๋ฃจํด ๋น๋์ธ launch๋ ์์ธ๊ฐ ๋ถ๋ชจ๋ก ์ ํ๋ฉ๋๋ค.
- ์ฝ๋ฃจํด ๋น๋์ธ async๋ ์์ธ๊ฐ Deferred ๊ฐ์ฒด์ ์ ์ฅ๋๋ฉฐ, await() ํธ์ถ ์ ์์ธ๊ฐ ๋์ ธ์ง๋๋ค.
- ์ฝ๋ฃจํด ๋น๋๋ ๋ค๋ฅธ ์ฝ๋ฃจํด์ ๊ณ์ ์คํ๋ฉ๋๋ค.
class ApiEcception(
val code: Int,
message: String,
): Throwable(message)
fun getFollowersNumber(): Int
suspend fun getUserName(): String
suspend fun getTweets(): List<Tweet>
suspend fun getUserDetails(): Details = coroutineScope{
val userName = async { getUserName() }
val followersNumber = async { getFollowersNumber()}
Detail(userName.await() , followersNumber.await())
}
fun main() = runBlocking<Unit> {
val details = try {
getUserDetails()
} catch (e: ApiException) {
null
}
val tweets = async { getTeets() }
println("User: $details")
println("Tweets: ${tweets.await()}")
}
// User: null
// Tweets: [Tweet(text=Hellow, world)]
- ์ค๋จ ํจ์์์ ๋ณ๋ ฌ๋ก ์์ ์ ์ํํ ๊ฒฝ์ฐ coroutineScope๋ฅผ ํ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
coroutineScope ํ์ฉ
- coroutineScope๋ ์ค๋จ ๋ฉ์ธ ํจ์ ๋ณธ์ฒด๋ฅผ ๋ํํ ๋ ์ฃผ๋ก ์ฌ์ฉ๋ฉ๋๋ค.
- runBlocking ํจ์๋ฅผ coroutineScope๊ฐ ๋์ฒดํ ์ ์์ต๋๋ค.
suspend fun main(): Unit = coroutineScope {
launch {
delay(1000)
println("World")
}
println("Hello, ")
}
- coroutineScope ํจ์๋ ๊ธฐ์กด์ ์ค๋จ ์ปจํ ์คํธ์์ ๋ฒ์ด๋ ์๋ก์ด ์ค์ฝํ๋ฅผ ๋ง๋ค๋ฉฐ, ๋ถ๋ชจ๋ก๋ถํฐ ์ค์ฝํ๋ฅผ ์์๋ฐ๊ณ ๊ตฌ์กฐํ๋ ๋์์ฑ์ ์ง์ํฉ๋๋ค.
์ฝ๋ฃจํด ์ค์ฝํ ํจ์
- ์ค์ฝํ๋ฅผ ์์ฑํ๋ ๋ค์ํ ํจ์๊ฐ ์์ผ๋ฉฐ, coroutineScope์ ๋น์ทํ๊ฒ ๋์ํฉ๋๋ค.
- ์ฝ๋ฃจํด ์ค์ฝํ ํจ์๋ ์ฝ๋ฃจํด ๋น๋์ ํผ๋๋์ง๋ง, ๋ ํจ์๋ ๊ฐ๋ ์ ์ผ๋ก๋ ์ฌ์ฉํจ์ ์์ด์ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ์ฝ๊ฒ ๊ตฌ๋ถํ ์ ์์ต๋๋ค.
์ฝ๋ฃจํด ๋น๋(runBlocking์ ์ ์ธํ)์ฝ๋ฃจํด ์ค์ฝํ ํจ์
launch, async, produce | coroutineScope, supervisorScope, withContext, withTimeout |
CoroutineScope์ ํ์ฅ ํจ์ | ์ค๋จ ํจ์ |
CoroutineScope ๋ฆฌ์๋ฒ์ ์ฝ๋ฃจํด ์ปจํ ์คํธ๋ฅผ ์ฌ์ฉ | ์ค๋จ ํจ์์ ์ปจํฐ๋ด์์ด์ ๊ฐ์ฒด๊ฐ ๊ฐ์ง ์ฝ๋ฃจํด ์ปจํ ์คํธ๋ฅผ ์ฌ์ฉ |
์์ธ๋ Job์ ํตํด ๋ถ๋ชจ๋ก ์ ํ | ์ผ๋ฐ ํจ์์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ์์ธ ์ฒ๋ฆฌ |
๋น๋๊ธฐ์ธ ์ฝ๋ฃจํด์ ์์ | ์ฝ๋ฃจํด ๋น๋๊ฐ ํธ์ถ๋ ๊ณณ์์ ์ฝ๋ฃจํด ์์ |
- runBlocking์ ์ ์ธํ ์ด์ ๋ runBlocking์ ์ฝ๋ฃจํด ๋น๋๋ณด๋ค ์ฝ๋ฃจํด ์ค์ฝํ ํจ์์ ๋น์ทํ ์ ์ด ๋๋ง์๋ณด์ด๊ธฐ ๋๋ฌธ์ ๋๋ค.
- runBlocking ๋ํ ํจ์ ๋ณธ์ฒด๋ฅผ ๊ณง๋ฐ๋ก ํธ์ถํ๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ๋ฉฐ, runBlocking์ ๋ธ๋กํน ํจ์์ง๋ง ์ฝ๋ฃจํด ์ค์ฝํ ํจ์๋ ์ค๋จ ํจ์๋ผ๋ ์ ์ ๋๋ค.
- ๋ฐ๋ผ์ runBlocking์ ์ฝ๋ฃจํด ๊ณ์ธต์์ ๊ฐ์ฅ ์์์ ์์ผ๋ฉฐ, ์ฝ๋ฃจํด ์ค์ฝํ ํจ์๋ ์ค๊ฐ ๊ณ์ธต์ ์กด์ฌํฉ๋๋ค.
withContext
- withContext๋ coroutineScope์ ๋น์ทํ์ง๋ง ์ค์ฝํ์ ์ปจํ ์คํธ๋ฅผ ๋ณ๊ฒฝํ ์ ์๋ค๋ ํน์ง์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
- withContext์ ์ธ์๋ก ์ปจํ ์คํธ๋ฅผ ์ ๊ณตํ๋ฉด ์ฝ๋ฃจํด ๋น๋์ ๊ฐ์ ๋ฐฉ์์ผ๋ก ๋ถ๋ชจ ์ค์ฝํ์ ์ปจํ ์คํธ๋ฅผ ๋์ฒดํฉ๋๋ค.
withContext(CoroutineName("Child 1")) {
delay(1000)
log("Child 1")
}
- ์ฃผ๋ก ๊ธฐ์กด ์ค์ฝํ์ ์ปจํ ์คํธ๊ฐ ๋ค๋ฅธ ์ฝ๋ฃจํด ์ค์ฝํ๋ฅผ ์ค์ ํ๊ธฐ ์ํด ์ฌ์ฉํฉ๋๋ค.
launch(Dispatchers.Main) {
view.showProgressBar()
withContext(Dispathcers.IO){
filePepository.saveData(data)
}
view.hidePrgoressBar()
}
supervisorScope
- supervisorScope๋ ํธ์ถํ ์ค์ฝํ๋ก๋ถํฐ ์์๋ฐ์ coroutineScope๋ฅผ ๋ง๋ค๊ณ ์ง์ ๋ ์ค๋จ ํจ์๋ฅผ ํธ์ถํ๋ค๋ ์ ์์ coroutineScope์ ๋น์ทํฉ๋๋ค.
- ๋์ ์ฐจ์ด๋ ์ปจํ ์คํธ์ Job์ SupervisorJob์ผ๋ก ์ค๋ฒ๋ผ์ด๋ฉํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ์์ ์ฝ๋ฃจํด์ด ์์ธ๋ฅผ ๋์ง๋๋ผ๋ ์ทจ์๋์ง ์์ต๋๋ค.
fun main() = runBlocking {
println("Before")
supervisorScope {
launch {
delay(100)
throw Error()
}
launch {
delay(2000)
println("Done")
}
}
println("After")
}
// Before
// 1์ด ํ
// ์์ธ ๋ฐ์
// 1์ด ํ
// Done
// After
- supervisorScope๋ ์๋ก ๋ ๋ฆฝ์ ์ธ ์์ ์ ์์ํ๋ ํจ์์์ ์ฃผ๋ก ์ฌ์ฉ๋ฉ๋๋ค.
suspend fun notifyAnalytics(actions: List<UserAction>) =
supervisorScope {
actions.forEach { action ->
launch {
notifyAnalytics(action)
}
}
}
- async์ ํจ๊ป ์ฌ์ฉ
- async๋ฅผ ์ฌ์ฉํ๋ฉด ์์ธ๊ฐ ๋ถ๋ชจ๋ก ์ ํ๋๋ ๊ฑธ ๋ง๊ธฐ ์ํ ์ถ๊ฐ์ ์ธ ์์ธ ์ฒ๋ฆฌ๊ฐ ํ์ํฉ๋๋ค.
- await๋ฅผ ํธ์ถํ๊ณ async ์ฝ๋ฃจํด์ด ์์ธ๋ก ๋๋๊ฒ ๋๋ค๋ฉด await๋ ์์ธ๋ฅผ ๋ค์ ๋์ง๊ธฐ ๋ฉ๋๋ค.
- ๋ฐ๋ผ์ async์์ ๋ฐ์ํ๋ ์์ธ๋ฅผ ์ ๋ถ ์ฒ๋ฆฌํ๋ ค๋ฉด try-catch ๋ธ๋ก์ผ๋ก await ํธ์ถ์ ๋ํํด์ผ ํฉ๋๋ค.
// async๋ฅผ ํ์ฉํ ๊ฒฝ์ฐ
superviorScope {
articleRepositories
.map { async { it.fetchArticles() } }
.mapNotNull {
try {
it.await()
} catch (e: Throwable) {
e.printStackTrace()
null
}
}
}
- withContext(SupervisorJob())์ ์ฐ๋ฉด ์๋๋ ์ด์
- supervisorScope ๋์ withContext(SupervisorJob())์ ํ์ฉํ ๊ฒฝ์ฐ ์๋ชป ๋ ์ฝ๋๊ฐ ๋ ์ ์์ต๋๋ค.
- withContext๋ ์ฌ์ ํ ๊ธฐ์กด์ ๊ฐ์ง๊ณ ์๋ Job์ ์ฌ์ฉํ๋ฉฐ SupervisorJob()์ด ํด๋น ์ก์ ๋ถ๋ชจ๊ฐ ๋ฉ๋๋ค.
- ๋ฐ๋ผ์ ํ๋์ ์์ ์ฝ๋ฃจํด์ด ์์ธ๋ฅผ ๋์ง๋ค๋ฉด ๋ค๋ฅธ ์์๋ค ๋ํ ์ทจ์๊ฐ ๋ฉ๋๋ค.
- ๊ฒฐ๊ตญ SupervisorJob()์ด ํ์๊ฐ ์์ด์ง๋ฉฐ, withContext ๋ํ ์์ธ๋ฅผ ๋์ง๋๋ค.
withTimeout
- coroutineScope์ ๋น์ทํ ํจ์์ด๋ฉฐ, ์ค์ฝํ๋ฅผ ๋ง๋ค๊ณ ๊ฐ์ ๋ฐํํฉ๋๋ค.
- ์ธ์๋ก ๋ค์ด์จ ๋๋ค์์ ์คํํ ๋ ์๊ฐ ์ ํ์ด ์์ผ๋ฉฐ, ์๊ฐ์ด ๋๋ฌด ์ค๋ ๊ฑธ๋ฆฌ๋ฉด ๋๋ค์์ ์ทจ์ํ๊ณ TimeoutCancellationException์ ๋์ง๋๋ค.
- ์ด ๋ TimeoutCancellationException์ CancellationException์ ์๋ธํ์ ์ ๋๋ค.
suspend fun test(): Int = withTimeout(1500){
delay(1000)
println("Still thinking")
delay(1000)
prntln("Done!")
42
}
// 1 ์ด ํ
// Still thinking
// 0.5์ด ํ
// TimeoutCancellationException
- ์ด๋ ํ ์คํธํ ๋ ์ ์ฉํ๋ฉฐ, ํน์ ํจ์๊ฐ ์๊ฐ์ด ์ผ๋ง๋ ๊ฑธ๋ฆฌ๋์ง ํ์ธํ๋ ์ฉ๋๋ก๋ ์ฌ์ฉํ ์ ์์ต๋๋ค.
- runTest ๋ด๋ถ์์ ์ฌ์ฉํ๋ค๋ฉด, withTimeout์ ๊ฐ์ ์๊ฐ์ผ๋ก ์๋ํ๊ฒ ๋ฉ๋๋ค.
์ฝ๋ฃจํด ์ค์ฝํ ํจ์ ์ฐ๊ฒฐํ๊ธฐ
suspend fun calcuateAnswerOrNull(): User? =
withContext(Dispatchers.Default) {
withTimeoutOrNull(1000){
calcuateAnswer()
}
}
- ์๋ก ๋ค๋ฅธ ์ฝ๋ฃจํด ์ค์ฝํ ํจ์์ ๋ ๊ฐ์ง ๊ธฐ๋ฅ์ด ๋ชจ๋ ํ์ํ๋ค๋ฉด ์ฝ๋ฃจํด ์ค์ฝํ ํจ์์์ ๋ค๋ฅธ ๊ธฐ๋ฅ์ ๊ฐ์ง๋ ์ฝ๋ฃจํด ์ค์ฝํ ํจ์๋ฅผ ํธ์ถํ ์ ์์ต๋๋ค.
์ถ๊ฐ์ ์ธ ์ฐ์ฐ
- ์์ ์ ์ํํ๋ ๋์ค์ ์ถ๊ฐ์ ์ธ ์ฐ์ฐ์ ์ํํด์ผํ๋ ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค.
suspend fun showUserData() = coroutineScope {
val user = User(
name = name.await(), // async
profile = profie.await() // async
)
view.show(user)
launch {
repo.notifyProfileShown()
}
}
fun onCreate(){
viewModelScope.launch {
_progressBar.value = true
showUserData()
_progressBar.value = false
}
}
- ์ด ๋ฐฉ์์๋ ์๋์ ๊ฐ์ ๋ฌธ์ ์ ์ด ์์ต๋๋ค.
- [ ํจ์์ ๋ชฉ์ ์ ๋ฒ์ด๋ ์ง๋์น ๊ธฐ๋ค๋ฆผ ]
- coroutineScope๊ฐ ์ฌ์ฉ์ ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ๊ณ ๋ณด์ฌ์ค ํ notifyProfileShown()๋ฅผ ์คํํ๋ฏ๋ก, ์ฌ์ฉ์์ ๋ฐ์ดํฐ๋ฅผ ๋ก๋ํ ๋ ๋ํ๋ผ _progressBar๋ notifyProfileShown()๊ฐ ์ข ๋ฃ๋ ๋๊น์ง ๋ณด์ฌ์ง๋๋ค.
- ์ด๋ฐ ๊ฒฝ์ฐ showUserData() ํจ์๋ก๋ถํฐ ๊ธฐ๋ํ๋ ์ ์๋ฏธํ ์์ ์ ํ๋ค๊ณ ๋ณด๊ธฐ ์ด๋ ต์ต๋๋ค.
- [ ์ทจ์ ]
- ์ฝ๋ฃจํด์ ์์ธ๊ฐ ๋ฐ์ํ์ ๋ ๋ค๋ฅธ ์ฐ์ฐ์ ์ทจ์ํ๊ฒ ๋์ด์์ต๋๋ค.
- notifyProfileShown()์ด profie.await()์ ์ํด ์ทจ์๋๋ค๋ฉด ์ ์ฒด ๊ณผ์ ์ด ์ทจ์๋ ์ ์์ต๋๋ค.
- ์ด ๋ ํต์ฌ ๋์์ ์ํฅ์ ์ฃผ์ง ์๋ ์ถ๊ฐ์ ์ธ ์ฐ์ฐ์ด ์๋ ๊ฒฝ์ฐ ( ์์์๋ notifyProfileShown()) ๋ค๋ฅธ ์ค์ฝํ์์ ์์ํ๋ ํธ์ด ๋ซ์ต๋๋ค.
- ์ด ๋ ๊ฐ์ฅ ์ฌ์ด ๋ฐฉ๋ฒ์ ์ฐ์ฐ์ ์ํ ์ค์ฝํ๋ฅผ ์์ฑํ๋ ๊ฒ์ ๋๋ค.
val analyticsScope = CoroutineScope(SupervisorJob())
- ์ด๋ฅผ ํ์ฉํด์ ์ ์ฝ๋๋ฅผ ์๋์ฒ๋ผ ์์ ํ ์ ์์ต๋๋ค.
class ShowUserDataUseCase(
...
private val analyticsScope: CorotineScope,
){
suspend fun showUserData() = coroutineScope {
val user = User(
name = name.await(), // async
profile = profie.await() // async
)
view.show(user)
analyticsScope.launch {
repo.notifyProfileShown()
}
}
}
- ๋ค์ด๋ฐ ๋ ์ค์ฝํ๋ฅผ ์ ๋ฌํจ์ผ๋ก์จ ๋ ๋ฆฝ์ ์ธ ์์ ์ ์คํํ๋ค๋ ๊ฒ์ ๋ช ํํ๊ฒ ์๋ฆด ์ ์์ต๋๋ค.
- ๋ฐ๋ผ์ ์ค๋จ ํจ์๋ ์ฃผ์ ๋ ์ค์ฝํ์์ ์์ํ ์ฐ์ฐ์ด ๋๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ์ง ์์ต๋๋ค.
- ์ค์ฝํ๊ฐ ์ ๋ฌ๋์ง ์์ผ๋ฉด ์ค๋จ ํจ์๋ ๋ชจ๋ ์ฐ์ฐ์ด ์๋ฃ๋ ๋๊น์ง ์ข ๋ฃ๋์ง ์์ ๊ฑฐ๋ผ๋ ๊ฑธ ์์ํ ์ ์์ต๋๋ค.