рдЖрдЗрдП рдПрдХ рд╕реНрдерд┐рддрд┐ рджреЗрдЦреЗрдВ рдЬрд╣рд╛рдВ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рджреГрд╢реНрдп рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, ImageView, рдЬрд┐рд╕реЗ рд╣рдореЗрдВ рдкреНрд░рддрд┐рдкрд╛рджрди рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рддреИрдпрд╛рд░ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ - рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЗрд╕рдХреЗ рдЖрдХрд╛рд░, рдЖрдХрд╛рд░ рдХреА рдЧрдгрдирд╛ рдХрд░реЗрдВ, рдпрд╛ рдПрдХ рдзрдмреНрдмрд╛ рдкреНрд░рднрд╛рд╡ рд▓рд╛рдЧреВ рдХрд░реЗрдВ, рдЖрджрд┐ред рдпреЗ рдЧрдгрдирд╛ рдПрдХ рдорд╣рдВрдЧрд╛ рдСрдкрд░реЗрд╢рди рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЙрдиреНрд╣реЗрдВ рдкреГрд╖реНрдарднреВрдорд┐ рдереНрд░реЗрдб рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдирд╛ рдмреЗрд╣рддрд░ рд╣реИредрдЬреЗрд╡рд┐рд╕реНрдЯрд╛ рджрд╛рджрд╛рдЬреА рдПрдХ рд░рдирдмреЗрд▓ рдмрдирд╛рдПрдВрдЧреЗ рдФрд░ рдлрд┐рд░ рдкрд░рд┐рдгрд╛рдо рдХреЛ рдореБрдЦреНрдп рдзрд╛рд░рд╛ рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИрдВрдбрд▓рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ рдФрд░ рдЗрд╕реЗ рджреГрд╢реНрдп рдкрд░ рд▓рд╛рдЧреВ рдХрд░реЗрдВрдЧреЗ (рдкрд╣рд▓реА рдмрд╛рдд рдЬреЛ рдорди рдореЗрдВ рдЖрддреА рд╣реИ)редрдпрд╣ рдЕрдкрдиреЗ рдХреЛрд░рдЖрдЙрдЯреНрд╕ рдХреЗ рд╕рд╛рде рдПрдХ рдХреЛрд▓реНрдбреНрд░рди рдореЗрдВ рдЬрд▓реНрджреА рдФрд░ рдЖрд╕рд╛рдиреА рд╕реЗ рдХреИрд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдХреЛрдЯрд▓рд┐рди-рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рдПрдВ:inline fun <T> View.doAsync(
crossinline backgroundTask: (scope: CoroutineScope) -> T,
crossinline result: (T?) -> Unit) {
val job = CoroutineScope(Dispatchers.Main)
val attachListener = object : View.OnAttachStateChangeListener {
override fun onViewAttachedToWindow(p0: View?) {}
override fun onViewDetachedFromWindow(p0: View?) {
job.cancel()
removeOnAttachStateChangeListener(this)
}
}
this.addOnAttachStateChangeListener(attachListener)
job.launch {
val data = async(Dispatchers.Default) {
try {
backgroundTask(this)
} catch (e: Exception) {
e.printStackTrace()
return@async null
}
}
if (isActive) {
try {
result.invoke(data.await())
} catch (e: Exception) {
e.printStackTrace()
}
}
this@doAsync.removeOnAttachStateChangeListener(attachListener)
}
}
рдЕрдм рд╣рдо рдПрдХ рд╕реНрдерд┐рддрд┐ рдХрд╛ рдЕрдиреБрдХрд░рдг рдХрд░реЗрдВрдЧреЗ: рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ RecyclerView рд╣реИ, рдкреНрд░рддреНрдпреЗрдХ рдЖрдЗрдЯрдо рдореЗрдВ рдПрдХ рддрд╕реНрд╡реАрд░ рд╣реИред рд╢реЛ рд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдЗрд╕ рддрд╕реНрд╡реАрд░ рдХреЛ рдзреБрдВрдзрд▓рд╛ (рдзреБрдВрдзрд▓рд╛) рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдпрд╣рд╛рдВ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдПрд╕рд┐рдВрдХреНрд░реЛрдирд╛рдЗрдЬрд╝реЗрд╢рди рдХреЗ рдмрд┐рдирд╛ рдХреИрд╕реЗ рд╣реЛрдЧрд╛:inner class PostHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val ivTest = itemView.iv_test
fun bind() {
val bitmap = ...
val blurBitmap = bitmap?.addBlurShadow(Color.CYAN, 50.dp, 50.dp)
ivTest.setImageBitmap(blurBitmap)
}
}
рдкрд░рд┐рдгрд╛рдо:
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдХрд░реНрдорд┐рдпреЛрдВ рдХрд╛ рдиреБрдХрд╕рд╛рди рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИредрдЕрдм рд╣рдо рдЕрдкрдиреЗ рдХрд╛рд░реНрдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ:inner class PostHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val ivTest = itemView.iv_test
fun bind() {
val bitmap = ...
itemView.doAsync({ scope ->
return@doAsync bitmap?.addBlurShadow(Color.CYAN, 50.dp, 50.dp)
}, { it ->
ivTest.setImageBitmap(it)
})
}
}
рдкрд░рд┐рдгрд╛рдо:
рдкреВрд░реА рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рд╣рдо рджреГрд╢реНрдп рдХреЗ рдЬреАрд╡рди рдЪрдХреНрд░ рд╕реЗ рдЬреБрдбрд╝реЗ рд╣реИрдВред рдЗрд╕рд▓рд┐рдП, рдЬрдм рджреГрд╢реНрдп рдХреЛ рдорд╛рддрд╛-рдкрд┐рддрд╛ рд╕реЗ рдЕрд▓рдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдЖрдЗрдЯрдо рдХреЗ рдЦреЛ рдЬрд╛рдиреЗ рдкрд░, рдпрд╛ рдирд╖реНрдЯ рд╣реЛрдиреЗ рдкрд░ рдЦрдВрдб / рдЧрддрд┐рд╡рд┐рдзрд┐ рдореЗрдВ рд▓рдЧрд╛рддрд╛рд░ рд░рд┐рд╕рд╛рдЗрдХрд▓рд░ рдореЗрдВ рдРрд╕рд╛ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рд╣рдо рд╕реБрд░рдХреНрд╖рд┐рдд рд░реВрдк рд╕реЗ рдХреЛрд░рдЯрд╛рдЗрди рдХреЛ рд░реЛрдХ рдФрд░ рд░рджреНрдж рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╣ рдЬрд╛рдирддреЗ рд╣реБрдП рдХрд┐ рдкрд░рд┐рдгрд╛рдо рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣реАрдВ рдирд╣реАрдВ рд╣реИ, рджреГрд╢реНрдп рд╡рд┐рдирд╛рд╢ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рд╣реИредрдЗрд╕реЗ рд╕реНрдкрд╖реНрдЯ рдФрд░ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВ рдЖрдкрдХреЗ ViewHolder рдореЗрдВ рдРрд╕реЗ рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдФрд░ рд▓реЙрдЧ рдХреЛ рджреЗрдЦрдиреЗ рдХреА рд╕рд▓рд╛рд╣ рджреЗрддрд╛ рд╣реВрдВ:itemView.doAsync({ scope ->
logInfo("coroutine start")
var x = 0
while (x < 100 && scope.isActive) {
TimeUnit.MILLISECONDS.sleep(100)
logInfo("coroutine, position: $adapterPosition ${x++}")
}
logInfo("coroutine end")
}, {
logInfo("coroutine DONE")
})
рдФрд░ рдЖрдк рджреЗрдЦреЗрдВрдЧреЗ рдХрд┐ рдХреМрди рд╕рд╛ рд╡реНрдпреВрд╣реЛрд▓реНрдбрд░ рдЬреЛ рдХреЛрд░рдЯрд╛рдЗрди рдХрд╛рдо рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЬрд┐рд╕ рдкрд░ рдпрд╣ рд░рджреНрдж рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдХрд╛рдо рдХрд░рдирд╛ рдмрдВрдж рдХрд░ рджреЗрддрд╛ рд╣реИред