158 votes

Comment exécuter du code sur un thread d'arrière-plan sur Android ?

Je veux qu'un code s'exécute en arrière-plan de façon continue. Je ne veux pas le faire dans un service. Y a-t-il un autre moyen possible ?

J'ai essayé d'appeler le Thread dans ma classe Activity mais mon Activity reste en arrière-plan pendant un certain temps, puis s'arrête. Le site Thread ne fonctionne plus non plus.

class testThread implements Runnable {
        @Override
        public void run() {
            File file = new File( Environment.getExternalStorageDirectory(), "/BPCLTracker/gpsdata.txt" );
            int i = 0;

            RandomAccessFile in = null;

            try {
                in = new RandomAccessFile( file, "rw" );
            } catch (FileNotFoundException e) {
// TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
// TODO Auto-generated catch block
                e.printStackTrace();
            }
//String line =null;
            while ( true ) {
                HttpEntity entity = null;
                try {
                    if ( isInternetOn() ) {
                        while ( ( line = in.readLine() ) != null ) {

                            HttpClient client = new DefaultHttpClient();
                            String url = "some url";
                            HttpPost request = new HttpPost( url );
                            StringEntity se = new StringEntity( line );
                            se.setContentEncoding( "UTF-8" );
                            se.setContentEncoding( new BasicHeader( HTTP.CONTENT_TYPE, "application/json" ) );
                            entity = se;
                            request.setEntity( entity );
                            HttpResponse response = client.execute( request );
                            entity = response.getEntity();
                            i++;
                        }
                        if ( ( line = in.readLine() ) == null && entity != null ) {
                            file.delete();
                            testThread t = new testThread();
                            Thread t1 = new Thread( t );
                            t1.start();
                        }

                    } else {
                        Thread.sleep( 60000 );
                    } // end of else

                } catch (NullPointerException e1) {
                    e1.printStackTrace();
                } catch (InterruptedException e2) {
                    e2.printStackTrace();
                } catch (IOException e1) {
// TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }// end of while
        }// end of run

    }

418voto

Brandon Rude Points 4249

SI vous en avez besoin :

  1. exécuter du code sur un Thread en arrière-plan

  2. exécuter du code qui ne touche pas/ne met pas à jour l'interface utilisateur.

  3. exécuter un code (court) qui prendra tout au plus quelques secondes pour se terminer

Ensuite, utilisez le modèle propre et efficace suivant qui utilise AsyncTask :

AsyncTask.execute(new Runnable() {
   @Override
   public void run() {
      //TODO your background code
   }
});

48voto

Sandy09 Points 1397

Rappelez-vous que le fonctionnement en arrière-plan et le fonctionnement en continu sont deux tâches différentes.

Pour les processus de fond à long terme, les threads ne sont pas optimaux avec Android. Cependant, voici le code, et faites-le à vos risques et périls.

Pour l'aborder de la bonne manière, vous devez d'abord démarrer le service, puis à l'intérieur du service, vous devez démarrer la tâche Thread/Async qui doit être exécutable.

Rappelez-vous que le service et le fil s'exécutent en arrière-plan, mais que notre tâche doit faire des déclenchements (appels répétés) pour obtenir des mises à jour, c'est-à-dire qu'une fois la tâche terminée, nous devons rappeler la fonction pour la prochaine mise à jour.

Timer (déclenchement périodique), Alarme (déclenchement par base de temps), Broadcast (déclenchement par base d'événement), la récursion réveillera nos fonctions.

public static boolean isRecursionEnable = true;

void runInBackground() {
    if (!isRecursionEnable)
        // Handle not to start multiple parallel threads
        return;

    // isRecursionEnable = false; when u want to stop
    // on exception on thread make it true again  
    new Thread(new Runnable() {
        @Override
        public void run() {
            // DO your work here
            // get the data
            if (activity_is_not_in_background) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        // update UI
                        runInBackground();
                    }
                });
            } else {
                runInBackground();
            }
        }
    }).start();
}

Utilisation du service : Si vous lancez un service, il démarrera, exécutera la tâche, et se terminera après l'exécution de la tâche si le service n'est pas STICKY. Cette fin de service peut également être causée par une exception dans le code ou par l'utilisateur qui l'a tué manuellement à partir des paramètres.

START_STICKY (Sticky Service) est l'option donnée par Android pour que le service redémarre lui-même si le service est terminé.

Rappelez-vous la question différence entre le multiprocessing et le multithreading ? Le service est un processus d'arrière-plan (tout comme une activité sans interface utilisateur), De la même manière que vous lancez un thread dans l'activité pour éviter la charge sur le MainThread (Activity/UI thread), de la même manière vous devez lancer des threads sur le service pour éviter la charge sur le service.

En une seule déclaration, si vous voulez exécuter une tâche continue en arrière-plan, vous devez lancer un StickyService et exécuter le thread dans le service sur la base d'événements.

36voto

Josh Pinter Points 3814

3-Liner simple

Un moyen simple de le faire, que j'ai trouvé dans un commentaire de @awardak en Réponse de Brandon Rude :

new Thread( new Runnable() { @Override public void run() { 
  // Run whatever background code you want here.
} } ).start();

Je ne sais pas si, ou comment, cela est mieux que d'utiliser AsyncTask.execute mais cela semble fonctionner pour nous. Tout commentaire sur la différence serait apprécié.

Merci, @awardak ¡!

24voto

Sajmon Points 16675

Je veux qu'un code s'exécute en arrière-plan de façon continue. Je ne veux pas le faire dans un service. Y a-t-il un autre moyen possible ?

Le mécanisme le plus probable que vous recherchez est le suivant AsyncTask . Il est directement désigné pour exécuter un processus d'arrière-plan sur le fil d'arrière-plan. Son principal avantage est qu'il offre quelques méthodes qui s'exécutent sur le thread principal (UI) et permettent de mettre à jour votre UI si vous voulez annoncer à l'utilisateur l'avancement d'une tâche ou mettre à jour l'UI avec les données récupérées du processus d'arrière-plan.

Si vous ne savez pas comment commencer, voici un bon tutoriel :

Note : Il est également possible d'utiliser IntentService con ResultReceiver qui fonctionne aussi bien.

15voto

Qazi Fahim Farhan Points 843

Aujourd'hui, je cherchais cela et M. Brandon Rude a donné un excellente réponse . Malheureusement, AsyncTask est maintenant déprécié . Vous pouvez toujours l'utiliser, mais il vous donne un avertissement, ce qui est très ennuyeux. Une alternative est donc d'utiliser Executors comme ceci (en kotlin ):

        Executors.newSingleThreadExecutor().execute(Runnable {
            // todo: do your background tasks
            runOnUiThread{
                // update ui if you are in an activity
            }
            /*
            requireActivity().runOnUiThread {
               // update views / ui if you are in a fragment
            }
            */
        })

Et dans java ça ressemble à ça :

        Executors.newSingleThreadExecutor().execute(() -> {
            // todo: background tasks
            runOnUiThread(() -> {
                // todo: update your ui / view in activity
            });

            /*
            requireActivity().runOnUiThread((Runnable) () -> {
                // todo: update your ui / view in Fragment
            });
            */
        });

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X