рдирдорд╕реНрдХрд╛рд░, рд╣реЗрдмреНрд░!
рд╣рдо рдЖрдкрдХреЛ рдпрд╛рдж рджрд┐рд▓рд╛рддреЗ рд╣реИрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдкреНрд░рд╕рд┐рджреНрдз рдмрд┐рдЧ рдирд░реНрдб рд░реЗрдВрдЪ рдЧрд╛рдЗрдб рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХреА рдХреЛрдЯрд▓рд┐рди рднрд╛рд╖рд╛ рдкрд░
рд▓рдВрдмреЗ рд╕рдордп рд╕реЗ рдкреНрд░рддреАрдХреНрд╖рд┐рдд рдкреБрд╕реНрддрдХ рдХреЗ рд▓рд┐рдП рдкреВрд░реНрд╡-рдЖрджреЗрд╢ рд╣реИ ред рдЖрдЬ рд╣рдордиреЗ рдЖрдкрдХрд╛ рдзреНрдпрд╛рди рдХреЛрдЯрд▓рд┐рди рдХреЛрд░рдЯрд╛рдЗрди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдПрдХ рд▓реЗрдЦ рдХреЗ рдЕрдиреБрд╡рд╛рдж рдФрд░ рдПрдВрдбреНрд░реЙрдЗрдб рдореЗрдВ рдзрд╛рд░рд╛рдУрдВ рдХреЗ рд╕рд╛рде рд╕рд╣реА рдХрд╛рдо рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд▓рд╛рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред рд╡рд┐рд╖рдп рдкрд░ рдмрд╣реБрдд рд╕рдХреНрд░рд┐рдп рд░реВрдк рд╕реЗ рдЪрд░реНрдЪрд╛ рдХреА рдЬрд╛ рд░рд╣реА рд╣реИ, рдЗрд╕рд▓рд┐рдП, рдкреВрд░реНрдгрддрд╛ рдХреЗ рд▓рд┐рдП, рд╣рдо рдпрд╣ рднреА рд╕рд▓рд╛рд╣ рджреЗрддреЗ рд╣реИрдВ рдХрд┐ рдЖрдк
рдЗрд╕ рд▓реЗрдЦ рдХреЛ рд╣реИрдмрд░ рд╕реЗ рдФрд░ рдПрдХреНрд╕рдореЛрд░ рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рдмреНрд▓реЙрдЧ рд╕реЗ
рдЗрд╕ рд╡рд┐рд╕реНрддреГрдд рдкреЛрд╕реНрдЯ рдХреЛ рджреЗрдЦреЗрдВред
рдЬрд╛рд╡рд╛ / рдПрдВрдбреНрд░реЙрдЗрдб рдореЗрдВ рдЖрдзреБрдирд┐рдХ рдкреНрд░рддрд┐рд╕реНрдкрд░реНрдзреА рдлреНрд░реЗрдорд╡рд░реНрдХ рдХреЙрд▓рдмреИрдХ рдкрд░ рдирд░рдХ рдХреЛ рд╕рдВрдХреНрд░рдорд┐рдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЕрд╡рд░реБрджреНрдз рд░рд╛рдЬреНрдпреЛрдВ рдХреА рдУрд░ рдЬрд╛рддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдПрдВрдбреНрд░реЙрдЗрдб рдХреЗ рдкрд╛рд╕ рдереНрд░реЗрдб рд╕реБрд░рдХреНрд╖рд╛ рдХреА рдЧрд╛рд░рдВрдЯреА рджреЗрдиреЗ рдХрд╛ рдПрдХ рд╕рд░рд▓ рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИред
Kotlin coroutines рдПрдХ рдмрд╣реБрдд рдкреНрд░рднрд╛рд╡реА рдФрд░ рдкреВрд░реНрдг рдЯреВрд▓рдХрд┐рдЯ рд╣реИ рдЬреЛ рдкреНрд░рдмрдВрдз рдкреНрд░рддрд┐рдпреЛрдЧрд┐рддрд╛ рдХреЛ рдмрд╣реБрдд рдЖрд╕рд╛рди рдФрд░ рдЕрдзрд┐рдХ рдЙрддреНрдкрд╛рджрдХ рдмрдирд╛рддреА рд╣реИред
рд░реЛрдХреЗрдВ рдФрд░ рдмреНрд▓реЙрдХ рдХрд░реЗрдВ: рдХреНрдпрд╛ рдЕрдВрддрд░ рд╣реИCoroutines рдзрд╛рдЧреЗ рдХреА рдЬрдЧрд╣ рдирд╣реАрдВ рд▓реЗрддреЗ рд╣реИрдВ, рдмрд▓реНрдХрд┐ рдЙрдиреНрд╣реЗрдВ рдкреНрд░рдмрдВрдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд░реВрдкрд░реЗрдЦрд╛ рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВред рдХреЛрд░реБрдЯрд┐рди рдХрд╛ рджрд░реНрд╢рди рдПрдХ рдРрд╕реЗ рд╕рдВрджрд░реНрдн рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдирд╛ рд╣реИ рдЬреЛ рдЖрдкрдХреЛ рдореБрдЦреНрдп рдзрд╛рдЧреЗ рдХреЛ рдЕрд╡рд░реБрджреНрдз рдХрд┐рдП рдмрд┐рдирд╛ рдкреГрд╖реНрдарднреВрдорд┐ рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдХреЗ рд▓рд┐рдП
рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдХреЙрд░рдЯреАрди рдХрд╛ рд▓рдХреНрд╖реНрдп рдХреЙрд▓рдмреИрдХ рд╕реЗ рджреВрд░ рдХрд░рдирд╛ рдФрд░ рдкреНрд░рддрд┐рдпреЛрдЧрд┐рддрд╛ рдХреЛ рд╕рд░рд▓ рдмрдирд╛рдирд╛ рд╣реИред
рд╕рд░рд▓рддрдо рдЙрджрд╛рд╣рд░рдгрдХреЗ рд╕рд╛рде рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЪрд▓реЛ рд╕рдмрд╕реЗ рд╕рд░рд▓ рдЙрджрд╛рд╣рд░рдг рд▓реЗрддреЗ рд╣реИрдВ:
Main
(рдореБрдЦреНрдп рдзрд╛рдЧрд╛) рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдХреЛрд░рдЯрд╛рдЗрди рдЪрд▓рд╛рдПрдВред рдЗрд╕рдореЗрдВ, рд╣рдо
IO
рд╕реНрдЯреНрд░реАрдо рд╕реЗ рдЗрдореЗрдЬ рдирд┐рдХрд╛рд▓реЗрдВрдЧреЗ рдФрд░ рдЗрд╕ рдЗрдореЗрдЬ рдХреЛ
Main
рд╡рд╛рдкрд╕ рдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рднреЗрдЬреЗрдВрдЧреЗред
launch(Dispatchers.Main) { val image = withContext(Dispatchers.IO) { getImage() }
рдПрдХ рдПрдХрд▓-рдереНрд░реЗрдбреЗрдб рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд░реВрдк рдореЗрдВ рдХреЛрдб рд╕рд░рд▓ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЬрдм
getImage
рдХреЛ
IO
рдереНрд░реЗрдбреНрд╕ рдХреЗ рдЖрд╡рдВрдЯрд┐рдд рдкреВрд▓ рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдореБрдЦреНрдп рдзрд╛рдЧрд╛ рдореБрдлрд╝реНрдд рд╣реИ рдФрд░ рдХрд┐рд╕реА рдЕрдиреНрдп рдХрд╛рд░реНрдп рдХреЛ рд▓реЗ рд╕рдХрддрд╛ рд╣реИ! WithContext рдлрд╝рдВрдХреНрд╢рди рд╡рд░реНрддрдорд╛рди coroutine рдХреЛ рд░реЛрдХ рджреЗрддрд╛ рд╣реИ рдЬрдмрдХрд┐ рдЗрд╕рдХреА рдХреНрд░рд┐рдпрд╛ рдЪрд▓ рд░рд╣реА рд╣реИ (
getImage()
)ред рдЬреИрд╕реЗ рд╣реА
getImage()
рд░рд┐рдЯрд░реНрди рдФрд░ рдореБрдЦреНрдп рдзрд╛рдЧреЗ рд╕реЗ
looper
рдЙрдкрд▓рдмреНрдз рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ,
imageView.setImageBitmap(image)
рдореБрдЦреНрдп рдзрд╛рдЧреЗ рдореЗрдВ рдХрд╛рдо рдлрд┐рд░ рд╕реЗ рд╢реБрд░реВ рдХрд░реЗрдЧрд╛ рдФрд░
imageView.setImageBitmap(image)
рдХреЙрд▓
imageView.setImageBitmap(image)
ред
рджреВрд╕рд░рд╛ рдЙрджрд╛рд╣рд░рдг: рдЕрдм рд╣рдореЗрдВ 2 рдкреГрд╖реНрдарднреВрдорд┐ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рддрд╛рдХрд┐ рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗред рд╣рдо рдПрд╕рд┐рдВрдХреНрд╕ / рдкреНрд░рддреАрдХреНрд╖рд┐рдд рдпреБрдЧрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ рддрд╛рдХрд┐ рдпреЗ рджреЛрдиреЛрдВ рдХрд╛рд░реНрдп рд╕рдорд╛рдирд╛рдВрддрд░ рдореЗрдВ рдХрд┐рдП рдЬрд╛рдПрдБ, рдФрд░ рджреЛрдиреЛрдВ рдХрд╛рд░реНрдп рддреИрдпрд╛рд░ рд╣реЛрддреЗ рд╣реА рдореБрдЦреНрдп рдкрд░рд┐рдгрд╛рдо рдореЗрдВ рдЙрдирдХреЗ рдкрд░рд┐рдгрд╛рдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ:
val job = launch(Dispatchers.Main) { val deferred1 = async(Dispatchers.Default) { getFirstValue() } val deferred2 = async(Dispatchers.IO) { getSecondValue() } useValues(deferred1.await(), deferred2.await()) } job.join()
async
launch
рд╕рдорд╛рди рд╣реИ, рд▓реЗрдХрд┐рди рдбрд┐рдлрд░реНрдб (
Future
рдмрд░рд╛рдмрд░ рдПрдХ рдХреЛрдЯрд▓рд┐рди рдЗрдХрд╛рдИ) рджреЗрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрд╕рдХрд╛ рдкрд░рд┐рдгрд╛рдо
await()
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЬрдм рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рдмрд┐рдирд╛ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдпрд╣ рд╡рд░реНрддрдорд╛рди рдЧреБрдВрдЬрд╛рдЗрд╢ рдХреЗ рд▓рд┐рдП рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд╕рдВрджрд░реНрдн рдореЗрдВ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред
рдлрд┐рд░ рд╕реЗ, рдореБрдЦреНрдп рдзрд╛рдЧрд╛ рдореБрдХреНрдд рд░рд╣рддрд╛ рд╣реИ рдЬрдмрдХрд┐ рд╣рдо рдЕрдкрдиреЗ 2 рдореВрд▓реНрдпреЛрдВ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рддреЗ рд╣реИрдВред
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ,
launch
рдлрд╝рдВрдХреНрд╢рди
Job
рджреЗрддрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдСрдкрд░реЗрд╢рди рдкреВрд░рд╛ рд╣реЛрдиреЗ рддрдХ рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ - рдпрд╣
join()
рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рдХрд┐рд╕реА рднреА рдЕрдиреНрдп рднрд╛рд╖рд╛ рдХреА рддрд░рд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдЗрд╕ рдЪреЗрддрд╛рд╡рдиреА рдХреЗ рд╕рд╛рде рдХрд┐ рдпрд╣
рдХреЛрд░рдЯрд╛рдЗрди рдХреЛ рдирд┐рд▓рдВрдмрд┐рдд рдХрд░ рджреЗрддрд╛ рд╣реИ, рдФрд░ рдкреНрд░рд╡рд╛рд╣ рдХреЛ рдЕрд╡рд░реБрджреНрдз рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ ред
рднреЗрдЬрдиреЗрдХреЛрд░рдЖрдЙрдЯ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╕рдордп рдбрд┐рд╕реНрдкреИрдЪрд┐рдВрдЧ рдПрдХ рдкреНрд░рдореБрдЦ рдЕрд╡рдзрд╛рд░рдгрд╛ рд╣реИред рдпрд╣ рдХреНрд░рд┐рдпрд╛ рдЖрдкрдХреЛ рдПрдХ рдзрд╛рдЧреЗ рд╕реЗ рджреВрд╕рд░реЗ рдореЗрдВ "рдХреВрдж" рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИред
рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ рдХрд┐
Main
рдореЗрдВ рдкреНрд░реЗрд╖рдг рдХреЗ рд▓рд┐рдП рдмрд░рд╛рдмрд░ рдХреНрдпрд╛ рдЬрд╛рд╡рд╛ рдореЗрдВ рджрд┐рдЦрддрд╛ рд╣реИ, рдЕрд░реНрдерд╛рддреНред
runOnUiThread: public final void runOnUiThread(Runnable action) { if (Thread.currentThread() != mUiThread) { mHandler.post(action);
рдПрдВрдбреНрд░реЙрдЗрдб рдХреЗ рд▓рд┐рдП
Main
рд╕рдВрджрд░реНрдн рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди
Handler
рдЖрдзрд╛рд░рд┐рдд рдбрд┐рд╕реНрдкреИрдЪрд░ рд╣реИред рддреЛ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рдмрд╣реБрдд рд╣реА рдЙрдкрдпреБрдХреНрдд рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╣реИ:
launch(Dispatchers.Main) { ... } vs launch(Dispatchers.Main, CoroutineStart.UNDISPATCHED) { ... }
launch(Dispatchers.Main)
Runnable
to
Handler
рднреЗрдЬрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрд╕рдХрд╛ рдХреЛрдб рддреБрд░рдВрдд рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред
launch(Dispatchers.Main, CoroutineStart.UNDISPATCHED)
рд╡рд░реНрддрдорд╛рди рдереНрд░реЗрдб рдореЗрдВ рдЕрдкрдиреА рд▓реИрдореНрдмреНрдбрд╛ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЛ рддреБрд░рдВрдд рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдЧрд╛ред
Dispatchers.Main
ред рдореЗрди рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдЬрдм рдХреЛрд░рдЯрд╛рдЗрди рдХрд╛рдо рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░реЗ, рддреЛ рдЗрд╕реЗ рдореБрдЦреНрдп рдзрд╛рдЧреЗ рдореЗрдВ рдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ ; рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣реИрдВрдбрд▓рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЗрд╡реЗрдВрдЯ рд▓реВрдк рдореЗрдВ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рджреЗрд╢реА Android рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд░реВрдк рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рд╕рдЯреАрдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:
val Main: HandlerDispatcher = HandlerContext(mainHandler, "Main")
Android рдореЗрдВ рдкреНрд░реЗрд╖рдг рдХреА рдкреЗрдЪреАрджрдЧрд┐рдпреЛрдВ рдХреЛ рд╕рдордЭрдиреЗ рдореЗрдВ рдорджрдж рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдпрд╣рд╛рдБ рдПрдХ рдЕрдЪреНрдЫрд╛ рд▓реЗрдЦ рд╣реИ:
рдПрдВрдбреНрд░реЙрдЗрдб рдХреЛрд░ рдХреЛ рд╕рдордЭрдирд╛: рд▓реЛрдкрд░, рд╣реИрдВрдбрд▓рд░ рдФрд░ рд╣реИрдВрдбрд▓рд░рдереНрд░реЗрдб ред
Coroutine рдкреНрд░рд╕рдВрдЧрдХреЙрд░рдЯреАрди рд╕рдВрджрд░реНрдн (рдЬрд┐рд╕реЗ рдХреЙрд░рдЯреАрди рдореИрдиреЗрдЬрд░ рдХреЗ рд░реВрдк рдореЗрдВ рднреА рдЬрд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИ) рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдХрд┐рд╕ рдХреЛрдб рдореЗрдВ рдЙрд╕рдХреЗ рдХреЛрдб рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдпрджрд┐ рдЕрдкрд╡рд╛рдж рдХреЛ рдлреЗрдВрдХ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдХреНрдпрд╛ рдХрд░рдирд╛ рд╣реИ рдФрд░ рд░рджреНрдж рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдорд╛рддрд╛-рдкрд┐рддрд╛ рдХреЗ рд╕рдВрджрд░реНрдн рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддрд╛ рд╣реИред
val job = Job() val exceptionHandler = CoroutineExceptionHandler { coroutineContext, throwable -> whatever(throwable) } launch(Disaptchers.Default+exceptionHandler+job) { ... }
job.cancel()
рдЙрди рд╕рднреА
job.cancel()
рдХреЛ рд░рджреНрдж рдХрд░ рджреЗрдЧрд╛, рдЬрд┐рдирдХреЗ рдорд╛рддрд╛-рдкрд┐рддрд╛
job
ред рдПрдХ рдЕрдкрд╡рд╛рдж рд╣реИрдВрдбрд▓рд░ рдХреЛ рдЗрди рдХреЛрд░рдЖрдЙрдЯреНрд╕ рдореЗрдВ рдлреЗрдВрдХреЗ рдЧрдП рд╕рднреА рдЕрдкрд╡рд╛рдж рдкреНрд░рд╛рдкреНрдд рд╣реЛрдВрдЧреЗред
рдХреНрд╖реЗрддреНрд░coroutineScope
рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рддреНрд░реБрдЯрд┐ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХреЛ рд╕рд░рд▓
coroutineScope
рд╣реИ:
рдпрджрд┐ рдЗрд╕рдХреА рдХреЛрдИ рдмреЗрдЯреА рдХреЛрд░рдЖрдЙрдЯ рд╡рд┐рдлрд▓ рд╣реЛ рдЬрд╛рддреА рд╣реИ, рддреЛ рдкреВрд░рд╛ рджрд╛рдпрд░рд╛ рдФрд░ рд╕рднреА рдмрд╛рд▓ рд╡рд╛рд╣рд┐рдиреА рднреА рд░рджреНрдж рдХрд░ рджреА рдЬрд╛рдПрдВрдЧреАред
async
рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдпрджрд┐ рдорд╛рди рдирд┐рдХрд╛рд▓рдирд╛ рд╕рдВрднрд╡ рдирд╣реАрдВ рдерд╛, рдЬрдмрдХрд┐ рдПрдХ рдФрд░ рдХрд╛рд░реНрдп рдЬрд╛рд░реА рд░рд╣рд╛, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдХреНрд╖рддрд┐рдЧреНрд░рд╕реНрдд рд░рд╛рдЬреНрдп рд╣реИ, рдФрд░ рдЗрд╕рдХреЗ рд╕рд╛рде рдХреБрдЫ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
useValues
рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╕рдордп,
useValues
рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЗрд╡рд▓ рддрднреА рдХрд╣рд╛ рдЬрд╛рдПрдЧрд╛ рдЬрдм рджреЛрдиреЛрдВ рдорд╛рдиреЛрдВ рдХрд╛ рдирд┐рд╖реНрдХрд░реНрд╖рдг рд╕рдлрд▓ рд╣реЛрдЧрд╛ред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрджрд┐
deferred2
рд╡рд┐рдлрд▓ рд░рд╣рддрд╛ рд╣реИ, рддреЛ
deferred2
рд░рджреНрдж рдХрд░
deferred1
рдЬрд╛рдПрдЧрд╛ред
coroutineScope { val deferred1 = async(Dispatchers.Default) { getFirstValue() } val deferred2 = async(Dispatchers.IO) { getSecondValue() } useValues(deferred1.await(), deferred2.await()) }
рдЖрдк рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рдбрд┐рдлрд╝реЙрд▓реНрдЯ
CoroutineContext
рд╕реЗрдЯ рдХрд░рдиреЗ рдФрд░ рдЙрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреВрд░реА рдХрдХреНрд╖рд╛ рдХреЛ "рдХрд╛рд░реНрдпрдХреНрд╖реЗрддреНрд░ рдореЗрдВ рдбрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВ"ред
рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╡рд░реНрдЧ, рдЬреЛ
CoroutineScope
рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ:
open class ScopedViewModel : ViewModel(), CoroutineScope { protected val job = Job() override val coroutineContext = Dispatchers.Main+job override fun onCleared() { super.onCleared() job.cancel() } }
рдХреЛрд░рдЯрд╛рдЗрди рдореЗрдВ рдЪрд▓ рд░рд╣рд╛ рд╣реИ
рдбрд┐рдлрд╝реЙрд▓реНрдЯ
launch
рдпрд╛
async
рдкреНрд░рдмрдВрдзрдХ рдЕрдм рд╡рд░реНрддрдорд╛рди рд╕реНрдХреЛрдк рдкреНрд░рдмрдВрдзрдХ рдмрди рдЬрд╛рддрд╛ рд╣реИред
launch { val foo = withContext(Dispatchers.IO) { тАж }
рдХреЙрд░рдЯреАрди рдХрд╛ рд╕реНрд╡рд╛рдпрддреНрдд рдкреНрд░рдХреНрд╖реЗрдкрдг (рдХрд┐рд╕реА рднреА рдХреЛрд░рдЯрд╛рдЗрдирд╕реНрдХреЛрдк рдХреЗ рдмрд╛рд╣рд░):
GlobalScope.launch(Dispatchers.Main) {
рдЖрдк рдбрд┐рдлреЙрд▓реНрдЯ
Main
рдбрд┐рд╕реНрдкреИрдЪрд░ рдХреЛ рд╕реЗрдЯ рдХрд░рдХреЗ рднреА рдЖрд╡реЗрджрди рдХреЗ рд▓рд┐рдП рдЧреБрдВрдЬрд╛рдЗрд╢ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
object AppScope : CoroutineScope by GlobalScope { override val coroutineContext = Dispatchers.Main.immediate }
рдЯрд┐рдкреНрдкрдгреА- Coroutines Java рдХреЗ рд╕рд╛рде рдЗрдВрдЯрд░рдСрдкрд░реЗрдмрд┐рд▓рд┐рдЯреА рдХреЛ рд╕реАрдорд┐рдд рдХрд░рддрд╛ рд╣реИ
- рддрд╛рд▓реЗ рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░рд┐рд╡рд░реНрддрдирд╢реАрд▓рддрд╛ рдХреЛ рд╕реАрдорд┐рдд рдХрд░реЗрдВ
- Coroutines рдХреЛ рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рди рдХрд┐ рдзрд╛рдЧреЗ рдХреЛ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП
Dispatchers.Default
(рдФрд░ Main
...) рдореЗрдВ I / O рд╕реЗ рдмрдЪреЗрдВ - рдпрд╣ Dispatchers.IO рдХреЗ рд▓рд┐рдП рд╣реИ- рд╕реНрдЯреНрд░реАрдо рд╕рдВрд╕рд╛рдзрди рдХреА рдЦрдкрдд рд╣реЛрддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рдПрдХрд▓-рдереНрд░реЗрдбреЗрдб рд╕рдВрджрд░реНрднреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ
Dispatchers.Default
Android 5+ рдореЗрдВ рдкреЗрд╢ рдХрд┐рдП рдЧрдП ForkJoinPool
рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИ- рдЪреИрдирд▓реЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ Coroutines рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ
рдЪреИрдирд▓реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рддрд╛рд▓реЗ рдФрд░ рдХреЙрд▓рдмреИрдХ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдирд╛JetBrains рдкреНрд░рд▓реЗрдЦрди рд╕реЗ рдЪреИрдирд▓ рдкрд░рд┐рднрд╛рд╖рд╛:
Channel Channel
рд╡реИрдЪрд╛рд░рд┐рдХ рд░реВрдк рд╕реЗ BlockingQueue
рд╕рдорд╛рди рд╣реИред рдореБрдЦреНрдп рдЕрдВрддрд░ рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣ рдкреБрдЯ рдСрдкрд░реЗрд╢рди рдХреЛ рдмреНрд▓реЙрдХ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдпрд╣ рдПрдХ рд╕рд╕реНрдкреЗрдВрдб send
(рдпрд╛ рдиреЙрди-рдмреНрд▓реЙрдХрд┐рдВрдЧ offer
) рдХреЗ рд▓рд┐рдП рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЯреЗрдХ рдСрдкрд░реЗрд╢рди рдХреЛ рдмреНрд▓реЙрдХ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп, рдпрд╣ рдПрдХ рд╕рд╕реНрдкреЗрдВрдб receive
рд▓рд┐рдП рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред
рдЕрднрд┐рдиреЗрддрд╛рдУрдВрдЪреИрдирд▓реЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд░рд▓ рдЙрдкрдХрд░рдг рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:
Actor
ред
Actor
, рдлрд┐рд░ рд╕реЗ,
Handler
рд╕рдорд╛рди рд╣реИ: рд╣рдо рдХреЛрд░рдЯрд╛рдЗрди рдХреЗ рд╕рдВрджрд░реНрдн рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ (рдЕрд░реНрдерд╛рдд, рд╡рд╣ рдзрд╛рдЧрд╛ рдЬрд┐рд╕рдореЗрдВ рд╣рдо рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХрд░рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВ) рдФрд░ рдЗрд╕рдХреЗ рд╕рд╛рде рдПрдХ рдХреНрд░рдордмрджреНрдз рдХреНрд░рдо рдореЗрдВ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВред
рдмреЗрд╢рдХ, рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣рд╛рдВ рдХреЙрд░рдЯрд┐рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ;
рдЖрдк рдкрд╛рд╡рд░ рдФрд░ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХреЛрдб рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ - рд░реЛрдХреЗрдВ ред
рд╕рд┐рджреНрдзрд╛рдВрдд рд░реВрдк рдореЗрдВ,
actor
рдХрд┐рд╕реА рднреА рдХрдорд╛рдВрдб рдХреЛ coroutine рдЪреИрдирд▓ рдкрд░ рдкреБрдирд░реНрдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд░реЗрдЧрд╛ред рдпрд╣
рдПрдХ рдХрдорд╛рдВрдб рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреА рдЧрд╛рд░рдВрдЯреА рджреЗрддрд╛ рд╣реИ рдФрд░ рдЗрд╕рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рд╕рдВрдЪрд╛рд▓рди рдХреЛ рдкреНрд░рддрд┐рдмрдВрдзрд┐рдд рдХрд░рддрд╛ рд╣реИ ред рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдкреВрд░реА рддрд░рд╣ рд╕реЗ
synchronize
рдХреЙрд▓ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдиреЗ рдФрд░ рд╕рднреА рдереНрд░реЗрдбреНрд╕ рдХреЛ рдореБрдХреНрдд рд░рдЦрдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИ!
protected val updateActor by lazy { actor<Update>(capacity = Channel.UNLIMITED) { for (update in channel) when (update) { Refresh -> updateList() is Filter -> filter.filter(update.query) is MediaUpdate -> updateItems(update.mediaList as List<T>) is MediaAddition -> addMedia(update.media as T) is MediaListAddition -> addMedia(update.mediaList as List<T>) is MediaRemoval -> removeMedia(update.media as T) } } }
рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╣рдо рд╕реАрд▓ рдХрд┐рдП рдЧрдП рдХреЛрдЯрд▓рд┐рди рд╡рд░реНрдЧреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рдЪреБрдирдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХрд░рддреЗ рд╣реИрдВред
sealed class Update object Refresh : Update() class Filter(val query: String?) : Update() class MediaAddition(val media: Media) : Update()
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЗрди рд╕рднреА рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдХрддрд╛рд░рдмрджреНрдз рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЙрдиреНрд╣реЗрдВ рдХрднреА рднреА рд╕рдорд╛рдирд╛рдВрддрд░ рдореЗрдВ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
рдкрд░рд┐рд╡рд░реНрддрдирд╢реАрд▓рддрд╛ рдХреА рд╕реАрдорд╛рдУрдВ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХрд╛ рдпрд╣ рдПрдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рддрд░реАрдХрд╛ рд╣реИред
Android Life Cycle + CoroutinesрдПрдВрдбреНрд░реЙрдЗрдб рдпреВрдЬрд░ рдЗрдВрдЯрд░рдлреЗрд╕ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдиреЗ, рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд░рджреНрдж рдХрд░рдиреЗ рдФрд░ рдореБрдЦреНрдп рдзрд╛рдЧреЗ рдХреЛ рдУрд╡рд░рд▓реЛрдб рд╣реЛрдиреЗ рд╕реЗ рд░реЛрдХрдиреЗ рдХреЗ рд▓рд┐рдП рдЕрднрд┐рдиреЗрддрд╛ рдмрд╣реБрдд рдЙрдкрдпреЛрдЧреА рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред
рдЖрдЗрдП рдЗрд╕реЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХрд░реЗрдВ рдФрд░ рдЬрдм рдЧрддрд┐рд╡рд┐рдзрд┐ рдирд╖реНрдЯ рд╣реЛ рдЬрд╛рдП рддреЛ
job.cancel()
рдХреЙрд▓ рдХрд░реЗрдВред
class MyActivity : AppCompatActivity(), CoroutineScope { protected val job = SupervisorJob()
SupervisorJob
рдХреНрд▓рд╛рд╕ рдПрдХ рдЕрдкрд╡рд╛рдж рдХреЗ рд╕рд╛рде рдирд┐рдпрдорд┐рдд
Job
рд╕рдорд╛рди рд╣реИ рдЬреЛ рдХреЗрд╡рд▓ рдбрд╛рдЙрдирд╕реНрдЯреНрд░реАрдо рджрд┐рд╢рд╛ рдореЗрдВ рд░рджреНрдж рдХрд░рддрд╛ рд╣реИред
рдЗрд╕рд▓рд┐рдП, рдЬрдм рд╣рдо рдЙрдирдореЗрдВ рд╕реЗ рдПрдХ рдореЗрдВ рд╡рд┐рдлрд▓ рд╣реЛрддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рд╕рднреА рдХреЛрд░рдЖрдЙрдЯ рдХреЛ рд░рджреНрдж рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред
рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕рд╛рде рдЪреАрдЬреЗрдВ рдереЛрдбрд╝реА рдмреЗрд╣рддрд░ рд╣реЛрддреА рд╣реИрдВ
рдЬреЛ рдЖрдкрдХреЛ
CoroutineContext
рдХрд┐рд╕реА рднреА
View
рд╕реЗ рдЗрд╕
CoroutineContext
рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
val View.coroutineContext: CoroutineContext? get() = (context as? CoroutineScope)?.coroutineContext
рдЕрдм рд╣рдо рдпрд╣ рд╕рдм рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ,
setOnClick
рдлрд╝рдВрдХреНрд╢рди рдЕрдкрдиреЗ
setOnClick
рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдВрдпреБрдХреНрдд рдЕрднрд┐рдиреЗрддрд╛ рдмрдирд╛рддрд╛ рд╣реИред рдХрдИ рдирд▓ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдордзреНрдпрд╡рд░реНрддреА рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЛ рдирдЬрд░рдЕрдВрджрд╛рдЬ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдПрдПрдирдЖрд░ рддреНрд░реБрдЯрд┐рдпреЛрдВ (рдЖрд╡реЗрджрди рдХрд╛ рдЬрд╡рд╛рдм рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИ) рдХреЛ рдирд╖реНрдЯ рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдФрд░ рдЗрди рдХрд╛рд░реНрдпреЛрдВ рдХреЛ
Activity
рдХреЗ рджрд╛рдпрд░реЗ рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдЗрд╕рд▓рд┐рдП, рдЬрдм рдЧрддрд┐рд╡рд┐рдзрд┐ рдирд╖реНрдЯ рд╣реЛ рдЬрд╛рддреА рд╣реИ, рддреЛ рдпрд╣ рд╕рдм рд░рджреНрдж рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
fun View.setOnClick(action: suspend () -> Unit) {
рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╣рдордиреЗ
Channel
рдХреЛ
Conflated
рд╕реЗрдЯ рдХрд┐рдпрд╛ рд╣реИ рддрд╛рдХрд┐ рдпрд╣ рдХреБрдЫ рдШрдЯрдирд╛рдУрдВ рдХреЛ рдЕрдирджреЗрдЦрд╛ рдХрд░ рджреЗ рдпрджрд┐ рдЙрдирдореЗрдВ рд╕реЗ рдмрд╣реБрдд рд╕рд╛рд░реЗ рд╣реИрдВ рдпрджрд┐ рдЖрдк рдЙрдирдореЗрдВ рд╕реЗ рдХреЛрдИ рднреА рдЦреЛрдП рдмрд┐рдирд╛ рдШрдЯрдирд╛рдУрдВ рдХреЛ рдХрддрд╛рд░рдмрджреНрдз рдХрд░рдирд╛ рдкрд╕рдВрдж рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдЗрд╕реЗ
Channel.UNLIMITED
рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдлрд┐рд░ рднреА рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ ANR рддреНрд░реБрдЯрд┐рдпреЛрдВ рд╕реЗ рдмрдЪрд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред
рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд░рджреНрдж рдХрд░рдиреЗ рдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдк рдХреЛрд░рдЖрдЙрдЯ рдФрд░ рдЬреАрд╡рдирдЪрдХреНрд░ рдХреЗ рдврд╛рдВрдЪреЗ рдХреЛ рднреА рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ:
val LifecycleOwner.untilDestroy: Job get() { val job = Job() lifecycle.addObserver(object: LifecycleObserver { @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) fun onDestroy() { job.cancel() } }) return job }
рдХреЙрд▓рдмреИрдХ рдХреЗ рд╕рд╛рде рд╕реНрдерд┐рддрд┐ рдХреЛ рд╕рд░рд▓ рдмрдирд╛рдПрдВ (рднрд╛рдЧ 1)рдпрд╣рд╛рдВ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐
Channel
рд╕рд╛рде рдХреЙрд▓рдмреИрдХ-рдЖрдзрд╛рд░рд┐рдд рдПрдкреАрдЖрдИ рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЛ рдХреИрд╕реЗ рдмрджрд▓рдирд╛ рд╣реИред
рдПрдкреАрдЖрдИ рдЗрд╕ рддрд░рд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:
requestBrowsing(url, listener)
url
рдкрд░ рд╕реНрдерд┐рдд рдлрд╝реЛрд▓реНрдбрд░ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рддрд╛ рд╣реИредlistener
рдЗрд╕ рдлрд╝реЛрд▓реНрдбрд░ рдореЗрдВ рдкрд╛рдИ рдЧрдИ рдХрд┐рд╕реА рднреА рдореАрдбрд┐рдпрд╛ рдлрд╝рд╛рдЗрд▓ рдХреЗ рд▓рд┐рдП onMediaAdded(media: Media)
рдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИредlistener.onBrowseEnd()
рдлрд╝реЛрд▓реНрдбрд░ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рддреЗ рд╕рдордп рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ
рдпрд╣рд╛рдБ VLC рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХреЗ рд▓рд┐рдП рд╕рд╛рдордЧреНрд░реА рдкреНрд░рджрд╛рддрд╛ рдореЗрдВ рдкреБрд░рд╛рдирд╛
refresh
рдХрд╛рд░реНрдп рд╣реИ:
private val refreshList = mutableListOf<Media>() fun refresh() = requestBrowsing(url, refreshListener) private val refreshListener = object : EventListener{ override fun onMediaAdded(media: Media) { refreshList.add(media)) } override fun onBrowseEnd() { val list = refreshList.toMutableList() refreshList.clear() launch { dataset.value = list parseSubDirectories() } } }
рдЗрд╕реЗ рдХреИрд╕реЗ рд╕реБрдзрд╛рд░рд╛ рдЬрд╛рдП?рдПрдХ рдЪреИрдирд▓ рдмрдирд╛рдПрдВ рдЬреЛ
refresh
рдореЗрдВ рдЪрд▓реЗрдЧрд╛ред рдЕрдм рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХреЙрд▓рдмреИрдХ рдХреЗрд╡рд▓ рдореАрдбрд┐рдпрд╛ рдХреЛ рдЗрд╕ рдЪреИрдирд▓ рдкрд░ рдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд░реЗрдЧрд╛, рдФрд░ рдлрд┐рд░ рдЗрд╕реЗ рдмрдВрдж рдХрд░ рджреЗрдЧрд╛ред
рдЕрдм
refresh
рдлрдВрдХреНрд╢рди рдХреНрд▓рд┐рдпрд░ рд╣реЛ рдЧрдпрд╛ рд╣реИред рд╡рд╣ рдПрдХ рдЪреИрдирд▓ рдмрдирд╛рддрд╛ рд╣реИ, рд╡реАрдПрд▓рд╕реА рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИ, рдлрд┐рд░ рдореАрдбрд┐рдпрд╛ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рдмрдирд╛рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рддрд╛ рд╣реИред
select
рдпрд╛
consumeEach
рдмрдЬрд╛рдп
consumeEach
рдЖрдк рдореАрдбрд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рдиреЗ рдХреЗ
for
рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдЬреИрд╕реЗ рд╣реА
browserChannel
рдмрдВрдж рд╣реЛрдЧрд╛ рдпрд╣ рд▓реВрдк рдЯреВрдЯ рдЬрд╛рдПрдЧрд╛ред
private lateinit var browserChannel : Channel<Media> override fun onMediaAdded(media: Media) { browserChannel.offer(media) } override fun onBrowseEnd() { browserChannel.close() } suspend fun refresh() { browserChannel = Channel(Channel.UNLIMITED) val refreshList = mutableListOf<Media>() requestBrowsing(url)
рдХреЙрд▓рдмреИрдХ рдХреЗ рд╕рд╛рде рд╕реНрдерд┐рддрд┐ рдХреЛ рд╕рд░рд▓ рдмрдирд╛рдирд╛ (рднрд╛рдЧ 2): рд░реЗрдЯреНрд░реЛрдлрд┐рдЯрджреВрд╕рд░рд╛ рддрд░реАрдХрд╛: рд╣рдо рд╕рднреА рдХреЛрдЯрд▓рд┐рдирдХреНрд╕ рдХреЛрд░рдЯрд╛рдЗрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╣рдо рдПрдХ рдХреЛрд░рдЖрдЙрдЯ рдХреЛрд░ рдлреНрд░реЗрдорд╡рд░реНрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред
рджреЗрдЦреЗрдВ рдХрд┐ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ рдХреЙрд░рдЖрдЙрдЯ!
retrofitSuspendCall
рдлрд╝рдВрдХреНрд╢рди рдЗрд╕реЗ рдПрдХ
suspend
рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ
Retrofit Call
рдЕрдиреБрд░реЛрдз рд▓рдкреЗрдЯрддрд╛ рд╣реИред
suspendCoroutine
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ
suspendCoroutine
рд╣рдо
Call.enqueue
рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ coroutine рдХреЛ рд░реЛрдХрддреЗ рд╣реИрдВред рдЗрд╕ рддрд░рд╣ рд╕реЗ рджрд┐рдпрд╛ рдЧрдпрд╛ рдХреЙрд▓рдмреИрдХ
continuation.resume(response)
рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдЧрд╛ред рдлрд┐рд░ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рд╣реЛрдиреЗ рдкрд░ рд╕рд░реНрд╡рд░ рд╕реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рд╕рд╛рде рдХреЙрд░рдЯреАрди рдХреЛ рдлрд┐рд░ рд╕реЗ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП
continuation.resume(response)
рдХрд╣реЗрдВрдЧреЗред
рдЗрд╕рдХреЗ рдмрд╛рдж, рд╣рдореЗрдВ рдмрд╕ рдЕрдкрдиреЗ рд░реЗрдЯреНрд░реЛрдлрд╝рд┐рдЯ рдлрд╝рдВрдХреНрд╢рдВрд╕ рдХреЛ
retrofitSuspendCall
рдореЗрдВ рд╕рдВрдпреЛрдЬрд┐рдд рдХрд░рдХреЗ рдХреНрд╡реЗрд░реА рдкрд░рд┐рдгрд╛рдореЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ
retrofitSuspendCall
рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред
suspend inline fun <reified T> retrofitSuspendCall(request: () -> Call <T> ) : Response <T> = suspendCoroutine { continuation -> request.invoke().enqueue(object : Callback<T> { override fun onResponse(call: Call<T>, response: Response<T>) { continuation.resume(response) } override fun onFailure(call: Call<T>, t: Throwable) { continuation.resumeWithException(t) } }) } suspend fun browse(path: String?) = retrofitSuspendCall { ApiClient.browse(path) }
рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдиреЗрдЯрд╡рд░реНрдХ рдХреЛ рдЕрд╡рд░реБрджреНрдз рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рдХреЙрд▓ рд╕рдорд░реНрдкрд┐рдд рд░реЗрдЯреНрд░реЛрдлрд┐рдЯ рдереНрд░реЗрдб рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдХреЛрд░рдЖрдЙрдЯ рдпрд╣рд╛рдВ рд╣реИ, рд╕рд░реНрд╡рд░ рд╕реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░ рд░рд╣рд╛ рд╣реИ, рдФрд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣реАрдВ рдирд╣реАрдВ рд╣реИ!
рдпрд╣ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди
рдЧрд┐рд▓реНрдбрд░ / рдХреЛрдЯрд▓рд┐рди-рдХреЛрд░рдЯрд╛рдЗрди-рд░реЗрдЯреНрд░реЛрдлрд┐рдЯ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╕реЗ рдкреНрд░реЗрд░рд┐рдд рд╣реИред
рдЗрд╕реА рддрд░рд╣ рдХрд╛ рдПрдХ рдФрд░ рдкрд░рд┐рдгрд╛рдо рджреЗрдиреЗ рдХреЗ рд╕рд╛рде рдПрдХ
рдЬреЗрдХрд╡рд░реНрдЯрди / рд░реЗрдЯреНрд░реЛрдлрд┐рдЯ 2-рдХреЛрдЯрд▓рд┐рди-рдХреЛрд░рдЯрд╛рдЗрдиреНрд╕-рдПрдбреЗрдкреНрдЯрд░ рднреА рд╣реИред
рдЙрдкрд╕рдВрд╣рд╛рд░Channel
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрдИ рдЕрдиреНрдп рддрд░реАрдХреЛрдВ рд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ; рдЕрдзрд┐рдХ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ
рд▓рд┐рдП рдмреНрд░реЙрдбрдХрд╛рд╕реНрдЯрдиреЗрд▓ рджреЗрдЦреЗрдВ рдХрд┐ рдЖрдкрдХреЛ рдЙрдкрдпреЛрдЧреА рдорд┐рд▓ рд╕рдХрддрд╛ рд╣реИред
рдЖрдк
рдкреНрд░реЛрдбреНрдпреВрд╕ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЪреИрдирд▓ рднреА рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред
рдЕрдВрдд рдореЗрдВ, рдЪреИрдирд▓реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдпреВрдЖрдИ рдХреЗ рдШрдЯрдХреЛрдВ рдХреЗ рдмреАрдЪ рд╕рдВрдЪрд╛рд░ рдХреЛ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ: рдПрдбреЗрдкреНрдЯрд░
Channel
рдорд╛рдзреНрдпрдо рд╕реЗ рдЗрд╕рдХреЗ рдЯреБрдХрдбрд╝реЗ / рдЧрддрд┐рд╡рд┐рдзрд┐ рдкрд░ рдХреНрд▓рд┐рдХ рдХреА рдШрдЯрдирд╛рдУрдВ рдХреЛ рдкреНрд░рд╕рд╛рд░рд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реИ рдпрд╛, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП,
Actor
рдорд╛рдзреНрдпрдо рд╕реЗред