Je crée une application Android qui suit le modèle MVVM en utilisant Room et LiveData, mais je dois renvoyer l'ID de la dernière insertion dans une table car il est utilisé pour ajouter des valeurs dans une autre table où l'ID est la clé étrangère , Je sais que je peux obtenir ceci en le retournant depuis le DAO:
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()) } } }
Mais le problème est que je dois renvoyer une valeur de l'AsyncTask qui insère la nouvelle entrée, j'ai essayé l'approche expliquée dans cette question: Comment obtenir le résultat d'OnPostExecute () vers l'activité principale car AsyncTask est une classe distincte?
Mais dans mon cas, la méthode processFinish n'est jamais appelée.
C'est mon code:
@Dao interface TratamientoDao { @Insert fun insert(tratamiento : Tratamiento): Long }
Alors, comment puis-je renvoyer une valeur à partir d'une AsyncTask dans Kotlin?
4 Réponses :
Il y a probablement un moyen, mais je préfère utiliser des coroutines. Comme par exemple:
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) }
N'oubliez pas d'ajouter les coroutines à l'application build.gradle
implémentation "org.jetbrains.kotlinx: kotlinx-coroutines-android: 0.27.0-eap13 "
La meilleure façon de gérer AyncTask dans Kotlin est d'utiliser la bibliothèque Anko pour effectuer des tâches en arrière-plan. Cela simplifie beaucoup l'utilisation de celui-ci. Juste comme ceci:
doAsync { var result = runLongTask() uiThread { toast(result) } }
Pour plus d'informations, consultez cet article:
Je sais que cette réponse date d'un an, mais juste pour les nouveaux utilisateurs, cette bibliothèque est maintenant obsolète.
C'est le moyen de renvoyer une valeur d'AsyncTask que vous pouvez convertir en Kotlin et essayer ceci
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; } }
J'ai passé une journée entière à essayer de comprendre cela et, les co-routines étaient ma solution !!!
D'abord, créez votre objet AsyncTask ... N'oubliez pas d'utiliser le type de paramètre corrects à la place de tous
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() ) }
et ensuite, appelez-le (dans ce cas, à partir de l'activité principale)
@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 } }
J'ai passé une journée entière à comprendre comment cela fonctionne, la meilleure réponse et +1 pour l'utilisation de co-routines. Cependant juste une mise à jour, au lieu d'utiliser Dispatchers.Main, ce serait bien d'utiliser Dispatcher.IO
Evidemment
completionCode = null
donc vous ne pouvez appeler aucune méthode sur un objet nul. Vous pouvez passer votre AsyncValue dans le constructeur qui estthis
dans ce cas. CommeInsertTratamientoAsyncTask (tratamientoDao, this) .execute ()