web-dev-qa-db-fra.com

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

Je veux que du code s'exécute en arrière-plan en permanence. Je ne veux pas le faire dans un service. Y a-t-il un autre moyen possible?

J'ai essayé d'appeler la classe Thread dans mon Activity, mais ma Activity reste en arrière-plan pendant un moment puis s'arrête. La classe Thread cesse également de fonctionner.

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

    }
99
user2082987

Si tu as besoin de:

  1. exécuter du code sur un thread d'arrière-plan

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

  3. exécuter (code court) ce qui prendra au plus quelques secondes

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

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

N'oubliez pas que l'exécution en arrière-plan, l'exécution en continu sont deux tâches différentes.

Pour les processus d'arrière-plan à long terme, les threads ne sont pas optimaux avec Android. Cependant, voici le code et faites-le à vos risques et périls ...

Rappelez-vous que Service ou Thread fonctionnera en arrière-plan, mais notre tâche doit déclencher (appeler encore et encore) pour obtenir les mises à jour. En d'autres termes, une fois la tâche terminée, nous devons rappeler la fonction pour la prochaine mise à jour.

Timer (déclenchement périodique), Alarm (déclenchement de la base de temps), Broadcast (déclenchement de base d'événements), la récursivité 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();
}

tilisation du service: Si vous lancez un service, celui-ci démarrera, il exécutera la tâche et se terminera. après l'exécution de la tâche. résilié peut également être dû à une exception, ou l’utilisateur l’a supprimé manuellement des paramètres. START_STICKY (Sticky Service) est l'option proposée par Android. Ce service redémarre automatiquement si le service est interrompu.

Rappelez-vous la question différence entre le multitraitement et le multithreading? Le service est un processus en arrière-plan (tout comme une activité sans interface utilisateur), de la même manière dont vous lancez un thread dans l'activité pour éviter la charge sur le thread principal (Activity thread) , de la même manière que vous devez lancer des threads (ou des tâches asynchrones) sur le service pour éviter la charge sur le service.

Dans une seule instruction, si vous souhaitez exécuter une tâche d’arrière-plan continue, vous devez lancer StickyService et exécuter le fil dans le service de la base d’événements.

37
Sandeep P

Je veux que du code s'exécute en arrière-plan en permanence. Je ne veux pas le faire dans un service. Y a-t-il un autre moyen possible?

Le mécanizm probable que vous recherchez est AsyncTask . Il est directement désigné pour effectuer un processus d'arrière-plan sur un thread en arrière-plan. En outre, son principal avantage est qu'il offre quelques méthodes qui s'exécutent sur le fil principal (UI) et permettent de mettre à jour votre interface utilisateur si vous souhaitez annoncer à l'utilisateur des progrès dans la tâche ou mettre à jour l'interface utilisateur avec des données extraites du processus en arrière-plan.

Si vous ne savez pas comment commencer, voici le didacticiel de Nice:

Remarque: Il est également possible d'utiliser IntentService avec ResultReceiver , qui fonctionne également.

19
Simon Dorociak

Robospice est une alternative à AsyncTask. https://github.com/octo-online/robospice .

Certaines des fonctionnalités de robospice.

1.exécute les requêtes réseau de manière asynchrone (dans un arrière-plan AndroidService) (par exemple: REST à l'aide de Spring Android). Notifiez votre application, sur le fil de l'interface utilisateur, lorsque le résultat est prêt.

2.est fortement typé! Vous faites vos demandes en utilisant des POJO et vous obtenez des POJO en tant que résultats de demande.

3. N'imposez aucune contrainte sur les POJO utilisés pour les demandes ni sur les classes d'activité que vous utilisez dans vos projets.

4.caches résultats (dans Json avec Jackson et Gson, ou XML, ou des fichiers texte à plat, ou des fichiers binaires, même en utilisant ORM Lite).

5.notifie vos activités (ou tout autre contexte) du résultat de la requête réseau si et seulement si elles sont toujours vivantes

6.Aucune fuite de mémoire, comme Android Loaders, contrairement à Android AsyncTasks notifie vos activités sur leur thread d'interface utilisateur.

7. utilise un modèle de gestion des exceptions simple mais robuste.

Des échantillons pour commencer. https://github.com/octo-online/RoboSpice-samples .

Un exemple de robospice sur https://play.google.com/store/apps/details?id=com.octo.Android.robospice.motivations&feature=search_result .

2
Raghunandan
class Background implements Runnable {
    private CountDownLatch latch = new CountDownLatch(1);
    private  Handler handler;

    Background() {
        Thread thread = new Thread(this);
        thread.start();
        try {
            latch.await();
        } catch (InterruptedException e) {
           /// e.printStackTrace();
        }
    }

    @Override
    public void run() {
        Looper.prepare();
        handler = new Handler();
        latch.countDown();
        Looper.loop();
    }

    public Handler getHandler() {
        return handler;
    }
}
1
Geno Papashvili

Si vous avez besoin d'exécuter des threads avec des codes différents, voici un exemple:

Auditeur:

public interface ESLThreadListener {

    public List onBackground();

    public void onPostExecute(List list);

}

Classe de fil

public class ESLThread extends AsyncTask<Void, Void, List> {


    private ESLThreadListener mListener;

    public ESLThread() {

        if(mListener != null){

            mListener.onBackground();
        }
    }

    @Override
    protected List doInBackground(Void... params) {

        if(mListener != null){

            List list = mListener.onBackground();

            return list;
        }

        return null;
    }

    @Override
    protected void onPostExecute(List t) {
        if(mListener != null){

            if ( t != null) {
                mListener.onPostExecute(t);
            }
        }

    }


    public void setListener(ESLThreadListener mListener){

        this.mListener = mListener;
    }
}

Exécuter différents codes:

  ESLThread thread = new ESLThread();
                        thread.setListener(new ESLThreadListener() {
                            @Override
                            public List onBackground() {
                                List<EntityShoppingListItems>  data = RoomDB.getDatabase(context).sliDAO().getSL(fId);

                                return data;

                            }

                            @Override
                            public void onPostExecute(List t) {

                                List<EntityShoppingListItems> data = (List<EntityShoppingListItems>)t;
                                adapter.setList(data);
                            }
                        });

                        thread.execute();
0
Beyaz