Reputation: 366
I have a problem with AsyncTask in Kotlin , I'm actually new so please be cool :)
So the problem here , is that I would like to use the result value which is in onPostExecute(), in another class
Let me show you my code, Here is ProviderAsync() class in my Provider.kt file ( I just create an array of Hashmap which I want to use) :
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
}
And now here is my getThings() method in another file where i want to use the result value to get all elements of my 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)
}
}
Thanks and sorry for my English
Upvotes: 4
Views: 6250
Reputation: 30595
As of June 2020 AsyncTask
is DEPRECATED. It doesn't mean that the class will be removed any time soon, it means that Google is recommending that you move to something else. The docs recommend to use the standard java.util.concurrent
or Kotlin concurrency utilities instead.
Using the last one we can implement it as the following:
Create generic extension function on 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)
}
Use the function with any CoroutineScope
:
In 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"
})
}
}
In Activity
or Fragment
:
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"
})
To use viewModelScope
or lifecycleScope
add next line(s) to dependencies of the app's build.gradle file:
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$LIFECYCLE_VERSION" // for viewModelScope
implementation "androidx.lifecycle:lifecycle-runtime-ktx:$LIFECYCLE_VERSION" // for lifecycleScope
At the time of writing final LIFECYCLE_VERSION = "2.3.0-alpha05"
Upvotes: 1
Reputation: 1516
You can take advantage of Kotlin's functional nature:
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)
}
}
then split the the callback logic in a separate function to pass it to ProviderAsync
constructor:
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)
}
}
Upvotes: 2