[JAVA] Programmation à partir de 51 ans Remarque AsyncTask --reference [Shakyo]

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

C'est une copie personnelle du livre. Je suis désolé s'il y a une erreur d'impression ou de traduction.

[Le résumé multi-thread est ici] (https://qiita.com/old_cat/items/a6d71f18a0789351c1a3)

public abstract class AsyncTask extends Object android.os.AsyncTask<Param,Progress,Result>

Comment est-ce commun avec le traitement des communications post-asynchrones et la généralisation d'AsyncTask? À propos

Présentation d'AsyncTask

AsyncTask gère facilement et correctement les threads de l'interface utilisateur. Il traite en arrière-plan et renvoie le résultat au thread d'interface utilisateur sans utiliser Thread ou Handler.

AsyncTask est conçu comme une classe d'assistance qui gère Thread, Handler, etc. (instanciation et utilisation: pas de méthode statique). Il n'est pas configuré pour être un framework de threads populaire.

AsyncTask peut être traité en quelques secondes. Si vous souhaitez thread pendant une longue période, utilisez les API fournies par le package java.util.concurrent, telles que ** Executor, ThreadPoolExecuter, FutureTask **.

Les tâches asynchrones sont définies par les résultats qui sont exécutés dans le thread d'arrière-plan et transmis au thread d'interface utilisateur? .. Autrement dit, il est défini dans les types d'arguments suivants et en quatre étapes.

Comment utiliser

AsyncTask est sous-classé et utilisé pour remplacer au moins une ou plusieurs méthodes (** doInBackground (Param ...) ) et, dans la plupart des cas, la seconde ( onPostExecute (Result)). **).

Voici un exemple de sous-classement

 private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
     protected Long doInBackground(URL... urls) {
         int count = urls.length;
         long totalSize = 0;
         for (int i = 0; i < count; i++) {
             totalSize += Downloader.downloadFile(urls[i]);
             publishProgress((int) ((i / (float) count) * 100));
             // Escape early if cancel() is called
             if (isCancelled()) break;
         }
         return totalSize;
     }

     protected void onProgressUpdate(Integer... progress) {
         setProgressPercent(progress[0]);
     }

     protected void onPostExecute(Long result) {
         showDialog("Downloaded " + result + " bytes");
     }
 }

Une fois générées, l'exécution des tâches est vraiment simple!

 new DownloadFilesTask().execute(url1, url2, url3);

Arguments AsyncTask <type générique>

AsyncTaskM<Param,Progress,Result>

  1. ** Param **
    Type de paramètre à passer à la tâche lors de l'exécution
  2. ** Progression **
    Le type d'unité de progression à afficher pendant le traitement en arrière-plan
  3. ** Résultat **
    Type de résultat du traitement en arrière-plan

Vous n'êtes pas obligé d'utiliser tous les types, vous pouvez le faire avec void. Comme ça

 private class MyTask extends AsyncTask<Void,Void,Void>

4 étapes

Lorsqu'une tâche asynchrone est exécutée, la tâche comporte quatre étapes.

  1. ** onPreExecute () **
    Une méthode préparatoire pour appeler le thread de l'interface utilisateur avant que la tâche ne soit traitée. Par exemple, lorsque vous souhaitez afficher la barre de progression lors de l'exécution d'Execute (), vous avez l'impression de vous préparer à afficher la barre de progression avec onPreExecute ().
  2. doInBackground (Params ...) </ font> </ strong>: remplacement requis
    onPreExecute () Appelé dans le thread d'arrière-plan immédiatement après le traitement .. C'est une étape utilisée pour le traitement qui est OK même si le traitement en arrière-plan prend du temps. Dans cette étape, les paramètres de la tâche asynchrone sont transmis. Le résultat du traitement est toujours renvoyé à cette étape et le résultat est passé à la dernière étape. Cette étape peut également être utilisée pour publishProgress (Progress), qui affiche les unités de progression, auquel cas elle sera affichée dans le thread de l'interface utilisateur à l'étape onProgressUpdate (Progress ...).
  3. ** onProgressUpdate (Progress ...) **
    Appelé par le thread d'interface utilisateur après l'exécution de publishProgress (Progress ...). Le moment de l'exécution n'est pas défini. Cette méthode est utilisée pour afficher divers formulaires de progression. Les formulaires de progression sont affichés dans l'interface utilisateur pendant le traitement en arrière-plan. Par exemple, la barre de progression de l'animation ou l'affichage du journal dans un champ de texte.
  4. ** onPostExecute (Result) **
    Appelé par le thread d'interface utilisateur une fois le traitement en arrière-plan terminé. Le résultat du traitement en arrière-plan est renvoyé en tant que paramètre dans cette étape.

Annulation de tâche

Utilisez cancel (boolea) pour annuler la tâche. Si vous exécutez cancel () (en cas de succès), isCancelled () sera appelé plus tard et retournera true. Normalement, lorsque doInBackground (java.lang.Object []) est exécuté, onPostExecute (java.lang.Object) est exécuté, mais lorsque cannel () est exécuté, onCannelled (java.lang.Object) est exécuté à la place de onPostExecute (). Le flux de sentiments qui s'exécute. DoInBackground (java.lang.Object []) émettra une valeur de retour de isCancelled () (true si annulée!) Pour vérifier si la tâche a été correctement annulée, alors vérifiez-la le plus rapidement possible!


Règles de thread

Il existe quelques règles pour utiliser correctement les threads.

--AsyncTask est appelée côté thread de l'interface utilisateur. Cela se produira automatiquement une fois que la version Android est JELLY_BEAN.

  • ** L'instance de tâche est créée du côté du thread de l'interface utilisateur **
  • ** Exécuter exécuter (Params ...) du côté de l'interface utilisateur **
  • N'appelez pas onPreExesute (), onPostExecute (Result), doInBackground (Prams ...), onProgressUpdate (Progress ...) directement. Laissez-le au système Android!
  • La tâche ne peut être exécutée qu'une seule fois. S'il est exécuté une deuxième fois, une exception sera levée.

Vérifier la mémoire

AsyncTask garantit que tous les appels de fonction de rappel sont synchronisés pour garantir que, sauf dans les cas de synchronisation explicites:

  • L'impact mémoire de onPreExecute (), l'impact mémoire des méthodes exécutées avant d'appeler execute (Params ...), etc. (construction de l'objet AsyncTask) sont affichés dans doInBackground (Params ...).
  • doInBackground(Params...) L'impact sur la mémoire est indiqué dans onPostExecute (Result) --L'impact sur la mémoire de doInBackgrund (Params ...) avant d'appeler publishProgress (Progres ...) est indiqué dans le onProgressUpdate (Progress ..) correspondant. Cependant, doInBackground (Params ...) continuera à s'exécuter, donc la mise à jour de doInBackground (Params ...) est en cours onProgressUpdata (Progress ...) Faites attention de ne pas interférer avec l'appel.
  • L'impact mémoire de cancel (boolean) est visible après un appel à isCancelled () (renvoie true dans le résultat de l'exécution) qui est appelé avant calquek (boolean), ou pendant ou après l'appel à onCancelled () Je vais.

Contexte d'AsyncTask

Initialement, les AsyncTasks étaient traitées séquentiellement dans un seul thread d'arrière-plan. À partir de Build.VERSION_CODES.DONUT, la version d'Android est devenue un pool de threads pour gérer le multitâche qui se traite en parallèle. À partir de la version Android Build.VERSION_CODES.HONEYCOMB, les tâches sont exécutées dans un seul thread pour éviter les erreurs d'application causées par la concurrence.

Si vous souhaitez effectuer un traitement parallèle </ font>, ** THREAD_POOL_EXECUTOR ** et ** executeOnExecutor ** (java.util.concurrent.Executor) Exécutez, java.lang.Object []) </ font>! ..

Aperçu

■ Nested classes

enum
AsiyncTask.Status
Indique l'état actuel de la tâche

■ Fields public static final Executor

SERIAL_EXECUTOR
Executor qui traite les tâches une par une
HREAD_POOL_EXECUTOR
Executor utilisé pendant le traitement parallèle

■ Public constructors

AsyncTask<>
Générer une nouvelle tâche de synchronisation

■ Public methods

final boolean cancel (boolean mayInterruptIfRunning)
Annuler la tâche < /td>
final AsyncTask execute (Params ... param)
Traiter la tâche avec des paramètres
static void execute (Runnable runnable)
execute (java.lang.Object) pour un traitement facile des objets Runnable simples
final AsyncTask executeOnExecutor (Executor exec, Params ... param>
Traiter la tâche en spécifiant des paramètres
final Result get(long timeout,TimeUnit unit)
Si le processus prend beaucoup de temps, attendez et obtenez le résultat
final Result get()
Attendez si nécessaire pour terminer le processus et obtenir le résultat
final AsyncTask.Status getStatus
Renvoie l'état actuel de la tâche
final boolean isCancelled()
Renvoie vrai si l'annulation réussit avant que la tâche ne se termine avec succès

Protected methods

abstract Result doInBackground(Params... params)
Une méthode qui remplace pour effectuer le traitement dans un thread d'arrière-plan
void onCancelled()
Remplacez onCancelled (java.lang.Object) si vous le pouvez!
void onCancelled(Result result)
Après avoir exécuté cancel (boolean) et doInBackground (java.lang.Object []) est terminé S'exécute sur les threads de l'interface utilisateur
void onPostExecute(Result result)
DoInBackground (Params ...) suivi d'un thread d'interface utilisateur
void onPreExecute()
Exécuter sur le fil de l'interface utilisateur avant doInBackground (Params ...)
void onProgressUpdate(Progress... values)
S'exécute sur le thread de l'interface utilisateur après l'appel de publishProgress (Progress ...)
final void publishProgress(Progress... values)
Cette méthode est appelée depuis doInBackground (Params ...) pour se mettre à jour dans le thread de l'interface utilisateur lors du traitement en arrière-plan
Méthode héritée
From class java.lang.Object

Résumé AsyncTask

Utiliser AsyncTask comme sous-classe AsyncTask<Params,Progress,Result>

--Spécifiez le type d'argument utilisé dans les paramètres
doInBackground () --Progress
Type de méthode pour afficher les informations en cours à l'utilisateur
Spécifiez le type d'argument à utiliser dans publishProgress (), onProgressUpdate () --Result
Méthode d'affichage des résultats
Spécifiez le type d'argument utilisé dans onPostExecute ()

Si AsyncTask ne nécessite aucun argument, AsyncTask \ <void, void, void>

Principales méthodes

  • execute()

  • publishProgress()

  • Méthode @ Override (laissez la trajectoire au système Android)

  • onPreExecute()

  • doInBackground()

  • onProgressUpdate()

  • onPostExecute()

・ Exécuter (Params ... params)

Une méthode à exécuter du côté du thread de l'interface utilisateur. Exécutez doInBackground en passant un argument à la méthode de substitution doInBackground ()! ..

Pour le type d'argument, reportez-vous au type d'argument de AsyncTask. L'argument est utilisé pour exécuter doInBackground ().

・ OnPreExecute

S'il y a un traitement que vous souhaitez faire avant d'exécuter Execute (), ici!

・ DoInBackground ()

Remplacez la méthode requise! </ font> Reçoit les arguments de execute () et traite les tâches en arrière-plan. Appelez onPostExecute () après le traitement doInBackground () et transmettez le résultat du traitement doInBackground () à onPostExecute (). Si vous utilisez cancel (), onCannelled () sera appelé à la place de onPostExecute (). doInBackground () est pour le traitement des tâches uniquement. Mettez à jour le fil de l'interface utilisateur avec d'autres méthodes!

・ OnPostExecute ()

Une méthode utilisée dans doInBackground () pour afficher le résultat de doInBackground () côté thread de l'interface utilisateur. Utilisez l'argument AsyncTask Result.

・ Progrès publié ()

S'il vous plaît lorsque vous souhaitez utiliser l'affichage de la progression! Lorsque vous exécutez publishProgress () sur doInBackground (), le système Android exécute onProgressUpdate () sur le thread d'interface utilisateur.

・ OnProgressUpdate ()

Lorsque vous exécutez publishProgress () sur doInBackground (), le système Android exécute onProgressUpdate () sur le thread d'interface utilisateur. Reportez-vous à l'argument d'AsyncTask pour l'argument


Exemple de code: execute () et doInBackground ()

--Subclass MainActivity.java
AsyncTask <> et exécutez execute () --Etendez la classe AsyncTask <> pour générer la classe MyAsyncTask
doInBackground () exécute le processus par execute () de MainActivity.java (to do). doInBackground () reçoit un argument de execute () et l'utilise pour le traitement.

public class MainActivity extends AppCompatActivity {

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

        //Créez une instance de tâche. exécuter exécuter()Argument surInBackground()Passer au
        // new MyAsyncTask().execute();Mais d'accord
        MyAsyncTask myAsyncTask = new MyAsyncTask();
        myAsyncTask.execute();

    }
}

class MyAsyncTask extends AsyncTask<Void,Void,Void> {
    @Override
    protected Void doInBackground(Void... aVoid) {
        // todo
        Log.d("msg","In MyAsyncTask");
        return null;
    }
}

Exemple de code: essayez d'ajouter des méthodes

Code qui modifie l'affichage de textView toutes les 3 secondes

  • MyActivity.onCreate()
    myAsncTask.excute("In doInBackground")
  • class MyAsyncTask
    • onPreExecute()
      textView.setText("onPreExecute")
    • doInBackground()
      sleep(10003) -> publishProgress(string[0]) -> sleep(10003) -> return "End doInBackground"
    • onProgressUpdate()
      textView.setText(string[0])
    • onPostExecute()
      textView.setText(s)
public class MainActivity extends AppCompatActivity {

    TextView textView;

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

        textView = findViewById(R.id.textView);

        //Créez une instance de tâche. exécuter exécuter()Argument surInBackground()Passer au
        // new MyAsyncTask<>.execute();Mais d'accord
        MyAsyncTask myAsyncTask = new MyAsyncTask();
        // doInBackground()Chaîne de caractères à("In doInBackground")Passer
        // onPreExecute()Après le traitement doInBackground()Courir
        myAsyncTask.execute("In doInBackground");

    }

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

        // execute("In doInBackground")Exécutez avant le traitement. Affichage dans le texte Vue du fil de l'interface utilisateur
        @Override
        protected void onPreExecute(){
            textView.setText("onPreExecute");
        }

        // execute()Chaîne de caractères de"In doInBackground"Recevoir
        @Override
        protected String doInBackground(String... string) {

            //Attendez 3 secondes
            try {
                sleep(1000*3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            //Afficher le texteView pendant le traitement doInBackground onPublishUpdate()Appel
            publishProgress(string[0]);

            //Attendez 3 secondes
            try {
                sleep(1000*3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // onPostExecute()Chaîne de caractères à"End doInBackground"donner
            return "End doInBackground";
        }

        //publierProgress dans doInBackground()Reçoit une chaîne de et l'affiche dans le textView du thread d'interface utilisateur
        protected void onProgressUpdate(String... string){
            textView.setText(string[0]);
        }

        // doInBackground()Valeur de retour de("End doInBackground")Est reçu et affiché dans le textView du thread de l'interface utilisateur
        @Override
        protected void onPostExecute(String s){
            textView.setText(s);
        }
    }
}

Passer les paramètres de Activity à AsyncTask

Passer plusieurs paramètres un par un

MainActivity


...
new MyAsyncTask().execute("param1","param2");

MyAsyncTask


...
@Override
protected String doInBackground(String... string){
   String param1 = string[0];
   String param2 = string[1];
return null
}

Passer plusieurs paramètres sous forme de tableau

MainActivity


Map<String,String> map = new HashMap<String,String>();
   map.put("param1","data1");
   map.put("param2","data2");
   map.put("param3","data3");

new MyAsyncTask().execute(map);

MyAsyncTask


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

   @Override
   protected Map<String,String> doInBackground(Map<String,String>... map){
      Map<String,String> mp = map[0];
      //Si mp est Json
      // JSONObject jsonMap = new JSONObject(mp);
      return mp;
   }

   @Override
   protected void onPostExecute(Map<String,String> mp){
      super.onPostExecute(mp);
      String val1 = mp.get("param1"); //data1 a été stocké dans val1
      String val2 = mp.get("param1"); //data2 a été stocké dans val2
      String val3 = mp.get("param3"); //data3 a été stocké dans val3
   }
}

Ça a pris du temps. La promenade de la tortue comme d'habitude.

Recommended Posts