Comment obtenir le résultat de OnPostExecute () sur l'activité principale car AsyncTask est une classe distincte?


362

J'ai ces deux cours. Ma principale activité et celui qui prolonge la AsyncTask, maintenant dans mon activité principale je dois obtenir le résultat de l' OnPostExecute()en AsyncTask. Comment passer ou obtenir le résultat de mon activité principale?

Voici les exemples de codes.

Mon activité principale.

public class MainActivity extends Activity{

    AasyncTask asyncTask = new AasyncTask();

    @Override
    public void onCreate(Bundle aBundle) {
        super.onCreate(aBundle);            

        //Calling the AsyncTask class to start to execute.  
        asyncTask.execute(a.targetServer); 

        //Creating a TextView.
        TextView displayUI = asyncTask.dataDisplay;
        displayUI = new TextView(this);
        this.setContentView(tTextView); 
    }

}

Ceci est la classe AsyncTask

public class AasyncTask extends AsyncTask<String, Void, String> {

TextView dataDisplay; //store the data  
String soapAction = "http://sample.com"; //SOAPAction header line. 
String targetServer = "https://sampletargeturl.com"; //Target Server.

//SOAP Request.
String soapRequest = "<sample XML request>";    



@Override
protected String doInBackground(String... string) {

String responseStorage = null; //storage of the response

try {


    //Uses URL and HttpURLConnection for server connection. 
    URL targetURL = new URL(targetServer);
    HttpURLConnection httpCon = (HttpURLConnection) targetURL.openConnection();
    httpCon.setDoOutput(true);
    httpCon.setDoInput(true);
    httpCon.setUseCaches(false); 
    httpCon.setChunkedStreamingMode(0);

    //properties of SOAPAction header
    httpCon.addRequestProperty("SOAPAction", soapAction);
    httpCon.addRequestProperty("Content-Type", "text/xml; charset=utf-8"); 
    httpCon.addRequestProperty("Content-Length", "" + soapRequest.length());
    httpCon.setRequestMethod(HttpPost.METHOD_NAME);


    //sending request to the server.
    OutputStream outputStream = httpCon.getOutputStream(); 
    Writer writer = new OutputStreamWriter(outputStream);
    writer.write(soapRequest);
    writer.flush();
    writer.close();


    //getting the response from the server
    InputStream inputStream = httpCon.getInputStream(); 
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
    ByteArrayBuffer byteArrayBuffer = new ByteArrayBuffer(50);

    int intResponse = httpCon.getResponseCode();

    while ((intResponse = bufferedReader.read()) != -1) {
        byteArrayBuffer.append(intResponse);
    }

    responseStorage = new String(byteArrayBuffer.toByteArray()); 

    } catch (Exception aException) {
    responseStorage = aException.getMessage(); 
    }
    return responseStorage;
}

protected void onPostExecute(String result) {

    aTextView.setText(result);

}       

}   

Vous pouvez créer une interface comme HelmiB expliqué ou vous pouvez créer un récepteur de diffusion local Vous pouvez voir l'exemple d'implémentation de récepteur de diffusion ici wiki.workassis.com/android-local-broadcast-receiver
Bikesh M

Pourquoi ne pas utiliser le modèle Observer?
JAAAY

Réponses:


751

Facile:

  1. Créez une interfaceclasse, où String outputest facultative, ou peut être n'importe quelle variable que vous souhaitez renvoyer.

    public interface AsyncResponse {
        void processFinish(String output);
    }
  2. Accédez à votre AsyncTaskclasse et déclarez l'interface en AsyncResponsetant que champ:

    public class MyAsyncTask extends AsyncTask<Void, Void, String> {
      public AsyncResponse delegate = null;
    
        @Override
        protected void onPostExecute(String result) {
          delegate.processFinish(result);
        }
     }
  3. Dans votre activité principale, vous devez vous implementsconnecter AsyncResponse.

    public class MainActivity implements AsyncResponse{
      MyAsyncTask asyncTask =new MyAsyncTask();
    
      @Override
      public void onCreate(Bundle savedInstanceState) {
    
         //this to set delegate/listener back to this class
         asyncTask.delegate = this;
    
         //execute the async task 
         asyncTask.execute();
      }
    
      //this override the implemented method from asyncTask
      @Override
      void processFinish(String output){
         //Here you will receive the result fired from async class 
         //of onPostExecute(result) method.
       }
     }

MISE À JOUR

Je ne savais pas que c'était un favori pour beaucoup d'entre vous. Voici donc la manière simple et pratique d'utiliser interface.

toujours en utilisant même interface. Pour info, vous pouvez combiner cela en AsyncTaskclasse.

en AsyncTaskclasse:

public class MyAsyncTask extends AsyncTask<Void, Void, String> {

  // you may separate this or combined to caller class.
  public interface AsyncResponse {
        void processFinish(String output);
  }

  public AsyncResponse delegate = null;

    public MyAsyncTask(AsyncResponse delegate){
        this.delegate = delegate;
    }

    @Override
    protected void onPostExecute(String result) {
      delegate.processFinish(result);
    }
}

faites cela dans votre Activityclasse

public class MainActivity extends Activity {

   MyAsyncTask asyncTask = new MyAsyncTask(new AsyncResponse(){

     @Override
     void processFinish(String output){
     //Here you will receive the result fired from async class 
     //of onPostExecute(result) method.
     }
  }).execute();

 }

Ou, implémentant à nouveau l'interface sur l'activité

public class MainActivity extends Activity 
    implements AsyncResponse{

    @Override
    public void onCreate(Bundle savedInstanceState) {

        //execute the async task 
        new MyAsyncTask(this).execute();
    }

    //this override the implemented method from AsyncResponse
    @Override
    void processFinish(String output){
        //Here you will receive the result fired from async class 
        //of onPostExecute(result) method.
    }
}

Comme vous pouvez voir 2 solutions ci-dessus, la première et la troisième, il faut créer une méthode processFinish, l'autre, la méthode est à l'intérieur du paramètre de l'appelant. Le troisième est plus soigné car il n'y a pas de classe anonyme imbriquée. J'espère que cela t'aides

Astuce : le changement String output, String responseet String resultà différents types de correspondance afin d'obtenir différents objets.


20
Totalement écrit tout cela et ensuite vu votre réponse :) Voici à penser de la même façon! +1. De cette façon, plusieurs choses peuvent écouter les résultats de la tâche AsyncTask!
Roloc

8
Je reçois une exception nullpointer car le délégué est défini sur null, veuillez le clearifier
Reyjohn

2
Juste une note pour les développeurs .net, on peut utiliser AutoResetEvents pour y parvenir et il y a aussi une implémentation java pour autoresetevents mais c'est beaucoup plus propre. Soit dit en passant, le thread ProcessFinish est-il sûr?
Syler

13
pour tous ceux qui obtiennent un pointeur nul, passez votre interface à votre constructeur de classe asyncTask puis affectez-la à une variable puis appelez processfinish () sur cette variable. Pour référence, voir la réponse acceptée. stackoverflow.com/questions/9963691/…
Sunny

2
@Sunny vous avez raison ... aussi, nous devons initialiser l'objet async pour async.delegate = this; au travail ..
Ninja_Coder

24

Il y a quelques options:

  • Incorporez la AsyncTaskclasse dans votre Activityclasse. En supposant que vous n'utilisez pas la même tâche dans plusieurs activités, c'est le moyen le plus simple. Tout votre code reste le même, vous déplacez simplement la classe de tâches existante pour qu'elle soit imbriquée dans la classe de votre activité.

    public class MyActivity extends Activity {
        // existing Activity code
        ...
    
        private class MyAsyncTask extends AsyncTask<String, Void, String> {
            // existing AsyncTask code
            ...
        }
    }
  • Créez un constructeur personnalisé pour votre AsyncTaskqui prend une référence à votre Activity. Vous instancieriez la tâche avec quelque chose comme new MyAsyncTask(this).execute(param1, param2).

    public class MyAsyncTask extends AsyncTask<String, Void, String> {
        private Activity activity;
    
        public MyAsyncTask(Activity activity) {
            this.activity = activity;
        }
    
        // existing AsyncTask code
        ...
    }

Dans la deuxième option: Pourquoi passer par la douleur d'un constructeur et d'un champ si la classe ne l'est pas static? Il suffit d' utiliser tout fieldOrMethodde MyActivityou MyActivity.this.fieldOrMethodsi elle est occulté.
TWiStErRob

@TWiStErRob La seconde suppose que ce MyAsyncTaskn'est pas une classe interne.
quietmint

1
Oh, désolé, private/ protectedpour les classes de niveau supérieur n'est pas autorisé, donc je pensais que ce devait être une staticclasse non interne.
TWiStErRob

2
Faites juste attention à ce que la classe interne AsyncTask puisse être une source de fuites de mémoire comme expliqué ici garena.github.io/blog/2014/09/10/android-memory-leaks
Mark Pazon

2
Conserver une référence d'activité est également une fuite de mémoire. L'approche de rappel est bien meilleure que cela
OneCricketeer

19

J'ai senti que l'approche ci-dessous est très facile.

J'ai déclaré une interface pour le rappel

public interface AsyncResponse {
    void processFinish(Object output);
}

Puis créé une tâche asynchrone pour répondre à tout type de requêtes parallèles

 public class MyAsyncTask extends AsyncTask<Object, Object, Object> {

    public AsyncResponse delegate = null;//Call back interface

    public MyAsyncTask(AsyncResponse asyncResponse) {
        delegate = asyncResponse;//Assigning call back interfacethrough constructor
    }

    @Override
    protected Object doInBackground(Object... params) {

      //My Background tasks are written here

      return {resutl Object}

    }

    @Override
    protected void onPostExecute(Object result) {
        delegate.processFinish(result);
    }

}

Appelé ensuite la tâche asynchrone en cliquant sur un bouton dans la classe d'activité.

public class MainActivity extends Activity{

    @Override
    public void onCreate(Bundle savedInstanceState) {

    Button mbtnPress = (Button) findViewById(R.id.btnPress);

    mbtnPress.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                MyAsyncTask asyncTask =new MyAsyncTask(new AsyncResponse() {

                    @Override
                    public void processFinish(Object output) {
                        Log.d("Response From Asynchronous task:", (String) output);

                        mbtnPress.setText((String) output);
                   }
                });

                asyncTask.execute(new Object[] { "Your request to aynchronous task class is giving here.." });


            }
        });

    }



}

Merci


17

Vous pouvez essayer ce code dans votre classe principale. Cela a fonctionné pour moi, mais j'ai mis en œuvre des méthodes d'une autre manière

try {
    String receivedData = new AsyncTask().execute("http://yourdomain.com/yourscript.php").get();
} 
catch (ExecutionException | InterruptedException ei) {
    ei.printStackTrace();
}

2
Pouvez-vous expliquer pourquoi cela aiderait OP à résoudre ce problème?
John Odom

3
Cela m'a aidé. J'ai essayé d'une autre manière comme la réponse de @HelmiB mais je n'obtiens aucun résultat
Nicu P

Ok désolé pour ma réponse. Elle doit appeler la classe AsyncTask, puis mettre un paramètre à cet appel. AsyncTask est défini par 3 types génériques: 1 paramètres (domaine du serveur ou autre paramètre) 2 progression (peut être annulée), 3 résultat. Tous ces types peuvent être: JSONObject, ou des chaînes, ou tout type de données. Lorsque vous avez une classe AsyncTask, vous devez définir où envoyer les données. ex: asyncTask.execute (" sampletargeturl.com"). get () ;
Nicu P

Lors de l'utilisation de cette méthode, j'ai reçu un avertissement sur Logcat: "I / Choreographer ﹕ Skipped 50 frames! L'application peut faire trop de travail sur son thread principal." Comment y faire face? L'interface utilisateur est-elle gelée en attendant le retour d'AsyncTask?
Huy Do

@NicuP vous avez peut-être oublié d'appeler execute(), voyez ma réponse, j'ai ajouté un commentaire là-bas. vous voudrez peut-être vérifier ma réponse mise à jour. J'espère que cela t'aides.
HelmiB

16

Cette réponse est peut-être en retard, mais je voudrais mentionner peu de choses lorsque vous Activitydépendez AsyncTask. Cela vous aiderait à éviter les plantages et la gestion de la mémoire. Comme déjà mentionné dans les réponses ci-dessus interface, nous les appelons également des rappels. Ils travailleront en tant qu'informateur, mais n'enverront jamais de référence forteActivity ou interfaceutiliseront toujours une référence faible dans ces cas.

Veuillez vous référer à la capture d'écran ci-dessous pour savoir comment cela peut causer des problèmes.

entrez la description de l'image ici

Comme vous pouvez le voir si nous avons commencé AsyncTaskavec une référence forte, il n'y a aucune garantie que notre Activity/ Fragmentsera vivant jusqu'à ce que nous obtenions des données, il serait donc préférable d'utiliser WeakReferencedans ces cas et cela aidera également à la gestion de la mémoire car nous ne tiendrons jamais la référence forte de notre Activityalors il sera éligible au ramassage des ordures après sa déformation.

Consultez l'extrait de code ci-dessous pour savoir comment utiliser WeakReference génial -

MyTaskInformer.java Interface qui fonctionnera comme un informateur.

public interface MyTaskInformer {

    void onTaskDone(String output);

}

MySmallAsyncTask.javaAsyncTask pour effectuer une tâche de longue durée, qui utilisera WeakReference.

public class MySmallAsyncTask extends AsyncTask<String, Void, String> {

    // ***** Hold weak reference *****
    private WeakReference<MyTaskInformer> mCallBack;

    public MySmallAsyncTask(MyTaskInformer callback) {
        this.mCallBack = new WeakReference<>(callback);
    }

    @Override
    protected String doInBackground(String... params) {

        // Here do whatever your task is like reading/writing file
        // or read data from your server or any other heavy task

        // Let us suppose here you get response, just return it
        final String output = "Any out, mine is just demo output";

        // Return it from here to post execute
        return output;
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);

        // Here you can't guarantee that Activity/Fragment is alive who started this AsyncTask

        // Make sure your caller is active

        final MyTaskInformer callBack = mCallBack.get();

        if(callBack != null) {
            callBack.onTaskDone(s);
        }
    }
}

MainActivity.javaCette classe est utilisée pour démarrer mon AsyncTaskimplémentation interfacesur cette classe et overridecette méthode obligatoire.

public class MainActivity extends Activity implements MyTaskInformer {

    private TextView mMyTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mMyTextView = (TextView) findViewById(R.id.tv_text_view);

        // Start your AsyncTask and pass reference of MyTaskInformer in constructor
        new MySmallAsyncTask(this).execute();
    }

    @Override
    public void onTaskDone(String output) {

        // Here you will receive output only if your Activity is alive.
        // no need to add checks like if(!isFinishing())

        mMyTextView.setText(output);
    }
}

2
C'est bien! un point important qui ne se remarque pas.
HasH

6

dans votre Oncreate ():

"

myTask.execute("url");
String result = "";
try {
      result = myTask.get().toString();
} catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
}catch (ExecutionException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();

} `


6

Vous pouvez le faire en quelques lignes, remplacez simplement onPostExecute lorsque vous appelez votre AsyncTask. Voici un exemple pour vous:

new AasyncTask()
{
    @Override public void onPostExecute(String result)
    {
       // do whatever you want with result 
    }
}.execute(a.targetServer);

J'espère que cela vous a aidé, codage heureux :)


Ça ne marche pas pour moi. Il n'entre simplement pas dans la onPostExecuteméthode.
Francisco Romero

4

Pourquoi les gens compliquent-ils la tâche?

Cela devrait être suffisant.

N'implémentez pas onPostExecute sur la tâche asynchrone, implémentez-le plutôt sur l'activité:

public class MainActivity extends Activity 
{

@Override
public void onCreate(Bundle savedInstanceState) {

    //execute the async task 
    MyAsyncTask task = new MyAsyncTask(){
            protected void onPostExecute(String result) {
                //Do your thing
            }       

    }

    task.execute("Param");

}


}

Cela fonctionne pour moi. C'est le plus simple et le plus facile à comprendre. Je pense qu'il utilise ce que Java est conçu pour faire. Merci. PS: Faut-il ajouter un @Override?
Old Geezer

1
Non. @Override n'est qu'une annotation. Vous dites donc au compilateur java que vous avez l'intention de remplacer la méthode et d'être informé si vous ne le faites pas.
bugdayci

4

Vous pouvez appeler la get()méthode de AsyncTask(ou la surcharge get(long, TimeUnit)). Cette méthode se bloquera jusqu'à ce que le AsyncTaskait terminé son travail, auquel cas il vous renverra le Result.

Il serait sage de faire un autre travail entre la création / démarrage de votre tâche asynchrone et l'appel de la getméthode, sinon vous n'utilisez pas la tâche asynchrone très efficacement.


1
Voté parce que get () bloquera le thread principal. Aucune raison d'utiliser AsyncTask s'il se bloque
GabrielBB

3

Vous pouvez écrire votre propre auditeur. C'est la même réponse que HelmiB mais semble plus naturel:

Créer une interface d'écoute:

public interface myAsyncTaskCompletedListener {
    void onMyAsynTaskCompleted(int responseCode, String result);
}

Écrivez ensuite votre tâche asynchrone:

public class myAsyncTask extends AsyncTask<String, Void, String> {

    private myAsyncTaskCompletedListener listener;
    private int responseCode = 0;

    public myAsyncTask() {
    }

    public myAsyncTask(myAsyncTaskCompletedListener listener, int responseCode) {
        this.listener = listener;
        this.responseCode = responseCode;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }


    @Override
    protected String doInBackground(String... params) {
        String result;
        String param = (params.length == 0) ? null : params[0];
        if (param != null) {
            // Do some background jobs, like httprequest...
            return result;
        }
        return null;
    }

    @Override
    protected void onPostExecute(String finalResult) {
        super.onPostExecute(finalResult);
        if (!isCancelled()) {
            if (listener != null) {
                listener.onMyAsynTaskCompleted(responseCode, finalResult);
            }
        }
    }
}

Enfin implémentez l'écouteur en activité:

public class MainActivity extends AppCompatActivity implements myAsyncTaskCompletedListener {

    @Override
    public void onMyAsynTaskCompleted(int responseCode, String result) {

        switch (responseCode) {
            case TASK_CODE_ONE: 
                // Do something for CODE_ONE
                break;
            case TASK_CODE_TWO:
                // Do something for CODE_TWO
                break;
            default: 
                // Show some error code
        }        
    }

Et voici comment vous pouvez appeler asyncTask:

 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Some other codes...
        new myAsyncTask(this,TASK_CODE_ONE).execute("Data for background job");
        // And some another codes...
}

2

Salut, vous pouvez faire quelque chose comme ça:

  1. Créer une classe qui implémente AsyncTask

    // TASK 
    public class SomeClass extends AsyncTask<Void, Void, String>>
    {
    
        private OnTaskExecutionFinished _task_finished_event;
    
        public interface OnTaskExecutionFinished
        {
            public void OnTaskFihishedEvent(String Reslut);
        }
    
        public void setOnTaskFinishedEvent(OnTaskExecutionFinished _event)
        {
            if(_event != null)
            {
                this._task_finished_event = _event;
            }
        }
    
        @Override
        protected void onPreExecute()
        {
            super.onPreExecute();
    
        }
    
        @Override
        protected String doInBackground(Void... params)
        {
            // do your background task here ...
    
            return "Done!";
        }
    
        @Override
        protected void onPostExecute(String result)
        {
            super.onPostExecute(result);
            if(this._task_finished_event != null)
            {
                this._task_finished_event.OnTaskFihishedEvent(result);
            }
            else
            {
                Log.d("SomeClass", "task_finished even is null");
            }
        }
    }
  2. Ajouter dans l'activité principale

    // MAIN ACTIVITY
    public class MyActivity extends ListActivity
    {
       ...
        SomeClass _some_class = new SomeClass();
        _someclass.setOnTaskFinishedEvent(new _some_class.OnTaskExecutionFinished()
        {
        @Override
        public void OnTaskFihishedEvent(String result)
        {
            Toast.makeText(getApplicationContext(),
                    "Phony thread finished: " + result,
                    Toast.LENGTH_SHORT).show();
        }
    
       });
       _some_class.execute();
       ...
     }

1

Créez un membre statique dans votre classe d'activité. Attribuez ensuite la valeur pendant laonPostExecute

Par exemple, si le résultat de votre AsyncTask est une chaîne, créez une chaîne statique publique dans votre activité

public static String dataFromAsyncTask;

Ensuite, dans le onPostExecuteAsyncTask, faites simplement un appel statique à votre classe principale et définissez la valeur.

MainActivity.dataFromAsyncTask = "result blah";


1
quelles sont les possibilités de fuite de mémoire dans ce scénario?
antroïde

0

Je le fais fonctionner en utilisant le filetage et le gestionnaire / message. Étapes comme suit: Déclarez une boîte de dialogue de progression

ProgressDialog loadingdialog;

Créez une fonction pour fermer la boîte de dialogue lorsque l'opération est terminée.

   private Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        loadingdialog.dismiss();

    }
    };

Codez vos détails d'exécution:

 public void startUpload(String filepath) {
    loadingdialog = ProgressDialog.show(MainActivity.this, "Uploading", "Uploading Please Wait", true);
    final String _path = filepath;
    new Thread() {
        public void run() {
            try {
                UploadFile(_path, getHostName(), getPortNo());
                handler.sendEmptyMessage(0);

            } catch (Exception e) {
                Log.e("threadmessage", e.getMessage());
            }
        }
    }.start();
}

0

Vous devez utiliser des «protocoles» pour déléguer ou fournir des données au AsynTask.

Délégués et sources de données

Un délégué est un objet qui agit au nom ou en coordination avec un autre objet lorsque cet objet rencontre un événement dans un programme. ( Définition Apple )

les protocoles sont des interfaces qui définissent certaines méthodes pour déléguer certains comportements.

Voici un exemple complet !!!


0

essaye ça:

public class SomAsyncTask extends AsyncTask<String, Integer, JSONObject> {

    private CallBack callBack;

    public interface CallBack {
        void async( JSONObject jsonResult );
        void sync( JSONObject jsonResult );
        void progress( Integer... status );
        void cancel();
    }

    public SomAsyncTask(CallBack callBack) {
        this.callBack = callBack;
    }

    @Override
    protected JSONObject doInBackground(String... strings) {

        JSONObject dataJson = null;

        //TODO query, get some dataJson

        if(this.callBack != null)
            this.callBack.async( dataJson );// asynchronize with MAIN LOOP THREAD

        return dataJson;

    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);

        if(this.callBack != null)
            this.callBack.progress(values);// synchronize with MAIN LOOP THREAD

    }

    @Override
    protected void onPostExecute(JSONObject jsonObject) {
        super.onPostExecute(jsonObject);

        if(this.callBack != null)
            this.callBack.sync(jsonObject);// synchronize with MAIN LOOP THREAD
    }

    @Override
    protected void onCancelled() {
        super.onCancelled();

        if(this.callBack != null)
            this.callBack.cancel();

    }
}

Et exemple d'utilisation:

public void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);

         final Context _localContext = getContext();
         SomeAsyncTask.CallBack someCallBack = new SomeAsyncTask.CallBack() {

                @Override
                public void async(JSONObject jsonResult) {//async thread
                    //some async process, e.g. send data to server...
                }

                @Override
                public void sync(JSONObject jsonResult) {//sync thread
                    //get result...

                    //get some resource of Activity variable...
                    Resources resources = _localContext.getResources();
                }

                @Override
                public void progress(Integer... status) {//sync thread
                    //e.g. change status progress bar...
                }

                @Override
                public void cancel() {

                }

            };

            new SomeAsyncTask( someCallBack )
                                .execute("someParams0", "someParams1", "someParams2");

    }

0

Je vais probablement un peu trop loin mais j'ai fourni des rappels pour le code d'exécution et les résultats. évidemment, pour la sécurité des threads, vous voulez faire attention à ce à quoi vous accédez dans votre rappel d'exécution.

L'implémentation AsyncTask:

public class AsyncDbCall<ExecuteType,ResultType> extends AsyncTask<ExecuteType, Void,  
ResultType>
{
    public interface ExecuteCallback<E, R>
    {
        public R execute(E executeInput);
    }
    public interface PostExecuteCallback<R>
    {
        public void finish(R result);
    }

    private PostExecuteCallback<ResultType> _resultCallback = null;
    private ExecuteCallback<ExecuteType,ResultType> _executeCallback = null;


    AsyncDbCall(ExecuteCallback<ExecuteType,ResultType> executeCallback, PostExecuteCallback<ResultType> postExecuteCallback)
    {
        _resultCallback = postExecuteCallback;
        _executeCallback = executeCallback;
    }

    AsyncDbCall(ExecuteCallback<ExecuteType,ResultType> executeCallback)
    {
        _executeCallback = executeCallback;
    }

    @Override
    protected ResultType doInBackground(final ExecuteType... params)
    {
        return  _executeCallback.execute(params[0]);
    }

    @Override
    protected void onPostExecute(ResultType result)
    {
        if(_resultCallback != null)
            _resultCallback.finish(result);
    }
}

Un rappel:

 AsyncDbCall.ExecuteCallback<Device, Device> updateDeviceCallback = new 
 AsyncDbCall.ExecuteCallback<Device, Device>()
    {
        @Override
        public Device execute(Device device)
        {
            deviceDao.updateDevice(device);
            return device;
        }
    };

Et enfin exécution de la tâche asynchrone:

 new AsyncDbCall<>(addDeviceCallback, resultCallback).execute(device);

0

J'espère que vous avez vécu cela , sinon veuillez lire.

https://developer.android.com/reference/android/os/AsyncTask

Selon la nature des données de résultat, vous devez choisir la meilleure option possible à laquelle vous pouvez penser.

C'est un excellent choix pour utiliser une interface

d'autres options seraient ..

  • Si la classe AsyncTask est définie dans la classe même dans laquelle vous souhaitez utiliser le résultat. Utilisez une variable globale statique ou get () , utilisez-la à partir de la classe externe ( variable volatile si nécessaire). mais doit être conscient de la progression de AsyncTask ou doit au moins s'assurer qu'il a terminé la tâche et que le résultat est disponible via la méthode variable / get () globale. vous pouvez utiliser l' interrogation, onProgressUpdate (Progress ...) , la synchronisation ou les interfaces (qui vous conviennent le mieux)

  • Si le résultat est compatible pour être une entrée sharedPreference ou s'il est correct d'être enregistré en tant que fichier dans la mémoire, vous pouvez l' enregistrer même à partir de la tâche d'arrière-plan elle-même et utiliser la méthode onPostExecute ()
    pour être averti lorsque le résultat est disponible dans la mémoire.

  • Si la chaîne est suffisamment petite et doit être utilisée au début d'une activité. il est possible d'utiliser des intentions ( putExtra () ) dans onPostExecute () , mais n'oubliez pas que les contextes statiques ne sont pas aussi sûrs à gérer.

  • Si possible, vous pouvez appeler une méthode statique à partir de la méthode onPostExecute (), le résultat étant votre paramètre

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.