Dmi*_*try 3 multithreading android android-asynctask kotlin
我花了一些时间来寻找一个开发人员友好的解决方案(不向项目添加依赖项)如何在后台线程中执行一些艰巨的任务,并在任务完成后将结果返回到主线程。我找到了允许这样做的“AsyncTask”。但是要使用它,您需要为需要在后台运行的每个任务编写样板代码。我是 iOS 开发者,决定尝试 Android 相关的开发。所以在 Swift 中你可以简单地使用下一个代码来完成这个任务:
DispatchQueue.global().async(execute: {
//Do some hard task in background
DispatchQueue.main.async(execute: {
//Return to main
})
})
Run Code Online (Sandbox Code Playgroud)
这看起来很简单。但是在 Kotlin 中我没有找到这么简单的解决方案,并决定创建它。
这是我做的:
我创建了通用类
import android.os.AsyncTask
class BaseAsyncTask<M>: AsyncTask<()->M, Int, M>() {
var completion: ((M)->Unit)? = null
override fun doInBackground(vararg params: (() -> M)?): M? {
for (p in params) {
return p?.invoke()
}
return null
}
override fun onPostExecute(result: M) {
super.onPostExecute(result)
completion?.invoke(result)
}
}
Run Code Online (Sandbox Code Playgroud)
和经理
class AsyncManager {
companion object {
fun <M>execute(inBackground: ()->M, inMain: (M)->Unit): BaseAsyncTask<M> {
val task = BaseAsyncTask<M>()
task.completion = inMain
task.execute(inBackground)
return task
}
fun <M>execute(inBackground: ()->M): BaseAsyncTask<M> {
val task = BaseAsyncTask<M>()
task.execute(inBackground)
return task
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在我像这样使用它:
AsyncManager.execute({
//Do some hard task in background
}, {
//Return to main
})
Run Code Online (Sandbox Code Playgroud)
看起来对开发人员友好。
Log.e("MAIN", "MAIN THREAD SHOULD NOT BE BLOCKED")
AsyncManager.execute({
Log.e("TASK", "Started background task")
val retval = "The value from background"
Thread.sleep(5000)
Log.e("TASK", "Finished background task with result: " + retval)
retval
}, {
Log.e("TASK", "Started task in Main thread with result from Background: " + it)
})
Log.e("MAIN", "MAIN THREAD SHOULD NOT BE BLOCKED - 1")
Run Code Online (Sandbox Code Playgroud)
和日志:
2019-03-27 17:11:00.719 17082-17082/com.test.testapp E/MAIN:不应阻塞主线程
2019-03-27 17:11:00.722 17082-17082/com.test.testapp E/MAIN:不应阻塞主线程 - 1
2019-03-27 17:11:00.722 17082-17124/com.test.testapp E/TASK:启动后台任务
2019-03-27 17:11:05.737 17082-17124/com.test.testapp E/TASK:完成后台任务,结果:来自后台的值
2019-03-27 17:11:05.738 17082-17082/com.test.testapp E/TASK:在主线程中启动任务,结果来自后台:来自后台的值
所以问题是专业的 Android 开发人员如何看待这个解决方案。如果我使用它,我会遇到什么问题。也许有一些理由不使用这个解决方案。
如果您使用 Kotlin,正确的方法是通过Coroutines,它允许您编写代码,例如:
// Launch a coroutine that by default goes to the main thread
GlobalScope.launch(Dispatchers.Main) {
// Switch to a background (IO) thread
val retval = withContext(Dispatchers.IO) {
Log.e("TASK", "Started background task")
val retval = "The value from background"
Thread.sleep(5000)
Log.e("TASK", "Finished background task with result: " + retval)
retval
}
// Now you're back the main thread
Log.e("TASK", "Started task in Main thread with result from Background: " + retval)
}
Run Code Online (Sandbox Code Playgroud)
请注意,Kotlin 协程在结构化并发下运行,因此您通常希望避免使用GlobalScope
,而是将协程范围绑定到您的 Activity / Fragment 生命周期。这通常需要您自己立即完成。
归档时间: |
|
查看次数: |
1668 次 |
最近记录: |