AsyncTask 在 Kotlin 中的使用

Posted

技术标签:

【中文标题】AsyncTask 在 Kotlin 中的使用【英文标题】:AsyncTask use in Kotlin 【发布时间】:2018-10-12 19:48:00 【问题描述】:

我在 Kotlin 中遇到了 AsyncTask 的问题,我实际上是新手,所以请冷静:)

所以这里的问题是,我想在另一个类中使用 onPostExecute() 中的结果值

让我给你看我的代码,这是我的 Provider.kt 文件中的 ProviderAsync() 类(我只是创建了一个我想要使用的 Hashmap 数组):

class ProviderAsync() : AsyncTask<HashMap<String, Any>, Void, ArrayList<HashMap<String, Any>>>() 

var allThings: ArrayList<HashMap<String, Any>> = arrayListOf()
override fun doInBackground(vararg params: HashMap<String, Any>): ArrayList<HashMap<String, Any>>? 
    for (i in 0..2000) 
        val thing = hashMapOf("Loc" to "fr", "name" to "class", "Id" to "23", "tuto" to "fr", "price" to 44)
        allThings.add(thing )
    
    return null


override fun onPreExecute() 
    super.onPreExecute()
    // ...


override fun onPostExecute(result: ArrayList<HashMap<String, Any>>?) 
    super.onPostExecute(result)
    // what can I do Here

现在这是我在另一个文件中的 getThings() 方法,我想在其中使用结果值来获取我的 Arraylist 的所有元素:

fun getThings(context: Context) 
        ProviderAsync().execute()
        var values = // Here i want the RESULT send from my AsyncTask
         for (i in 0..values.size) 

                        var myObject = convertToMyObject(values[i])
                        allTickets.add(myObject)
                    
        

感谢和抱歉我的英语

【问题讨论】:

首先让我知道您为什么不在要使用返回值的同一类中编写异步任务? 这是我的架构,我希望我的 Provider 执行 AsyncTask 并将数据发送给我的 Manager 参考this。 您为什么使用HashMap&lt;String, Any?&gt;而不是class之类的东西? 【参考方案1】:

您可以利用 Kotlin 的功能特性:

class ProviderAsync(private val callback: (things: ArrayList<HashMap<String, Any>>) -> Unit) : AsyncTask<HashMap<String, Any>, Void, ArrayList<HashMap<String, Any>>>() 

    var allThings: ArrayList<HashMap<String, Any>> = arrayListOf()
    override fun doInBackground(vararg params: HashMap<String, Any>): ArrayList<HashMap<String, Any>>? 
        for (i in 0..2000) 
            val thing = hashMapOf("Loc" to "fr", "name" to "class", "Id" to "23", "tuto" to "fr", "price" to 44)
            allThings.add(thing)
        
        return null
    

    override fun onPreExecute() 
        super.onPreExecute()
        // ...
    

    override fun onPostExecute(result: ArrayList<HashMap<String, Any>>) 
        super.onPostExecute(result)

        //callback function to be executed after getting the result
        callback(result)
    

然后将回调逻辑拆分到一个单独的函数中传递给ProviderAsync构造函数:

fun getThings(context: Context) 
        ProviderAsync(::asyncTaskCallback).execute()


fun asyncTaskCallback(values: ArrayList<HashMap<String, Any>>) 
    for (i in 0..values.size) 

        var myObject = convertToMyObject(values[i])
        allTickets.add(myObject)
    

【讨论】:

【参考方案2】:

截至 2020 年 6 月,AsyncTask已弃用。这并不意味着该课程很快就会被删除,这意味着 Google 建议您转到其他课程。 docs recommend to use 改为标准的java.util.concurrent 或Kotlin concurrency utilities。

使用最后一个,我们可以如下实现:

    CoroutineScope上创建通用扩展函数:

     fun <R> CoroutineScope.executeAsyncTask(
             onPreExecute: () -> Unit,
             doInBackground: () -> R,
             onPostExecute: (R) -> Unit
     ) = launch 
         onPreExecute()
         val result = withContext(Dispatchers.IO)  // runs in background thread without blocking the Main Thread
             doInBackground()
         
         onPostExecute(result)
      
    

    使用任何CoroutineScope的函数:

    ViewModel:

    class MyViewModel : ViewModel() 
    
        fun someFun() 
            viewModelScope.executeAsyncTask(onPreExecute = 
                // ... runs in Main Thread
            , doInBackground = 
                // ... runs in Worker(Background) Thread
                "Result" // send data to "onPostExecute"
            , onPostExecute = 
                // runs in Main Thread
                // ... here "it" is the data returned from "doInBackground"
            )
        
    
    

    ActivityFragment

    lifecycleScope.executeAsyncTask(onPreExecute = 
        // ... runs in Main Thread
    , doInBackground = 
        // ... runs in Worker(Background) Thread
        "Result" // send data to "onPostExecute"
    , onPostExecute = 
        // runs in Main Thread
        // ... here "it" is the data returned from "doInBackground"
    )
    

    要使用viewModelScopelifecycleScope 将下一行添加到应用的build.gradle 文件的依赖项:

    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$LIFECYCLE_VERSION" // for viewModelScope
    implementation "androidx.lifecycle:lifecycle-runtime-ktx:$LIFECYCLE_VERSION" // for lifecycleScope
    

    在撰写本文时final LIFECYCLE_VERSION = "2.3.0-alpha05"

【讨论】:

以上是关于AsyncTask 在 Kotlin 中的使用的主要内容,如果未能解决你的问题,请参考以下文章

在 Kotlin 的 AsyncTask 中启动新活动

使用 Kotlin 显示来自 AsyncTask 的 Toast 消息

Kotlin中的? 、?. 、?: 、!!、as?

IOException: AsyncTask Image Download Kotlin Android (Bad File Descriptor)

AsyncTask 作为 kotlin 协程

如何在 Kotlin 中使用协程将图像保存在设备中