Reputation: 1322
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
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
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
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
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