2015-12-30 2 views
0

J'utilise un service lié pour exécuter des tâches gourmandes en arrière-plan, comme recommandé pour éviter les ANR. L'application cliente envoie des messages au service lié qui les gère dans la méthode handleMessage() de son Handler.L'application cliente peut-elle supprimer une demande en cours sans détruire le service et perdre le contexte associé?

Étant donné que certaines demandes peuvent prendre beaucoup de temps à répondre, je souhaite offrir à l'utilisateur la possibilité d '«annuler/abandonner» une demande en cours. Cependant, je ne peux pas détruire le service parce que je dois garder son contexte pour de futures demandes. L'envoi d'une requête "abandon" à partir de l'application sera mis en file d'attente et traité par le service après qu'il aura terminé sa tâche en cours, ce qui est évidemment trop tard et n'applique pas la fonctionnalité demandée.

Y a-t-il un moyen pour l'application cliente de tuer une requête en cours sans détruire le service et perdre son contexte associé?

* EDIT * Merci à la recommandation de Mario et ce link, voici la solution que je l'ai mis en œuvre:

ExecutorService executor = Executors.newFixedThreadPool(1); 
    private volatile static Future<?> BackgroundSolveFuture = null; 

    public class IncomingHandler extends Handler { 

    @Override 
    public void handleMessage(Message message) { 
     msg = message; 
     msgArg1 = message.arg1; 
     msgWhat = message.what; 

     if (message.replyTo != null) { 
      mClient = new Messenger(message.replyTo.getBinder()); 
     } 

     switch (msgWhat) { 
      case MSG_ABORT: 
       BackgroundSolveFuture = null; 
       break; 
      case MSG_SOLVE:case MSG_ANALYZE:case MSG_SUGGEST:case MSG_STEP: 
       BackgroundSolveFuture = executor.submit(new Runnable() { 
        public void run() { 
         solve(); 
        } 
       }); 
       break; 
      ... 

intérieur solve() Je vérifie régulièrement si BackgroundSolveFuture a été mis à null:

 if (BackgroundSolveFuture == null) { 
      undoAction(true); 
      return; 
     } 
+0

poster votre code 'Service' – pskink

Répondre

1

oui.

votre idée avec l'envoi d'un message d'abandon est correcte.

vous avez juste besoin de créer un nouveau fil pour chaque tâche. Par exemple, vous avez deux types de messages DOIT et ABORT, lorsque vous recevez un message DOIT vous créez et exécutez un nouveau thread avec une tâche, vous pouvez même garder une référence à ce thread.

Cela permet de terminer rapidement une méthode handleMessage(). Puis un nouveau message vient: ABORT, vous avez une référence au thread et vous pouvez interrompre le thread/tâche.