Eduardo Corona
Eduardo Corona

Reputation: 1322

Returning a value from AsyncTask in Kotlin

I'm making an Android app that follows the MVVM pattern using Room and LiveData, but I need to return the ID of the last insertion in one table because is used to add values in other table where the ID is the foreign key, I know that I can achive this returning it from the DAO:

@Dao
interface TratamientoDao {
    @Insert
    fun insert(tratamiento : Tratamiento): Long
}

But the problem is that I need to return a value from the AsyncTask that inserts the new entry,I tried the approach explained in this question: How to get the result of OnPostExecute() to main activity because AsyncTask is a separate class?

But In my case the method processFinish is never called.

This is my code:

interface AsyncValue{
    fun processFinish(lastID: Long?) : Long?
}

class TratamientoRepository (application: Application): AsyncValue {

    val tratamientoDao : TratamientoDao

    init{
        val database = MMRDataBase.getInstance(application)
        tratamientoDao = database.tratamientoDao()
    }

    fun insert(tratamiento: Tratamiento) : Long? {
        InsertTratamientoAsyncTask(tratamientoDao).execute(tratamiento)
        return 45
    }

    override fun processFinish(lastID: Long?): Long? {
        Log.d("ValorIngresado:", lastID.toString())
        return lastID
    }


    private class InsertTratamientoAsyncTask constructor(private val tratamientoDao: TratamientoDao) : AsyncTask<Tratamiento, Void, Long>(){

        var  completionCode : AsyncValue? = null
        override fun doInBackground(vararg params: Tratamiento): Long?{

            return tratamientoDao.insert(params[0])
        }

        override fun onPostExecute(result: Long?) {
           completionCode?.processFinish(result)
            //Log.i("TAMANO", result.toString())

        }

    }

}

So, How can I return a value from an AsyncTask in Kotlin?

Upvotes: 1

Views: 5197

Answers (4)

Diego Favero
Diego Favero

Reputation: 2115

I spent a full day trying to figure this and, co-routines was my solution !!!

First, create your AsyncTask Object ... Do not forget to use corrects parameter type instead all Any

@SuppressLint("StaticFieldLeak")
class AsyncTaskExample(private var activity: MainActivity?) : AsyncTask<Any, Int, Any?>() {

    override fun onPreExecute() {
        super.onPreExecute()
        // do pre stuff such show progress bar
    }

    override fun doInBackground(vararg req: Any?): Any? {

        // here comes your code that will produce the desired result
        return result 

    }

    // it will update your progressbar
    override fun onProgressUpdate(vararg values: Int?) {
        super.onProgressUpdate(*values)

    }


    override fun onPostExecute(result: Any?) {
        super.onPostExecute(result)

        // do what needed on pos execute, like to hide progress bar
        return
    }

}

and Then, call it ( in this case, from main activity )

var task = AsyncTaskExample(this)
var req = { "some data object or whatever" }

GlobalScope.launch( context = Dispatchers.Main){

   task?.execute(req)
}

GlobalScope.launch( context = Dispatchers.Main){

   println( "Thats the result produced by doInBackgorund: " +  task?.get().toString() )
}

Upvotes: 3

Riyasa Mansil
Riyasa Mansil

Reputation: 190

This is the way to return a value from AsyncTask you can convert in to Kotlin and try this

public class MyClass extends Activity {

 private class myTask extends AsyncTask<Void, Void, String> { 

    protected Void doInBackground(String... params) { 
      //do stuff return results; 
    } 

   @Override protected void onPostExecute(String result) { 
     //do stuff 
     myMethod(myValue); 
   } 
 }

 private myValueType myMethod(String myValue) { 
   //handle value 
   return myValueType; 
 } 
}

Upvotes: 1

piedra97
piedra97

Reputation: 37

The best way to handle AyncTask in Kotlin is using the Anko library for doing background task. It simplifies a lot the use of it. Just like this:

doAsync {
    var result = runLongTask()
    uiThread {
        toast(result)
    }
}

For more information check this article:

https://antonioleiva.com/anko-background-kotlin-android/

Upvotes: 0

Pedro R.
Pedro R.

Reputation: 673

There is probably a way, but I prefer using coroutines. Like for example:

val tratamiento = GetTratamiento()//or whatever you do to get the object
var result = 0
var scope = CoroutineScope(Job() + Dispatchers.IO)
scope.launch {
  result = tratamientoDao.insert(tratamiento)
}

Remember to add the coroutines to the app build.gradle

implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:0.27.0-eap13"

Upvotes: 2

Related Questions