2013-04-02 4 views
0

Mon intention est de créer une minuterie qui démarre à partir de 00:00:00 et se bloque avec une fonction d'enregistrement. Cet enregistrement est fait dans un service ainsi, le temporisateur est également dans le même service. Si l'application passe à l'arrière-plan, l'enregistrement et donc la minuterie continuent et l'application sélectionne le temps passé sur onResume avec un myService.getTime().Fonction minuterie en service (type de chronomètre)

Mais j'éprouve deux choses étranges. Le premier est que mon minuteur parfois allé plus vite qu'une seconde, parfois plus lent, saute parfois par exemple de 00:00:04 à 00:00:06, etc. aucune consitency dedans. J'utilise le code ci-dessous, mais il pourrait y avoir une meilleure option pour résoudre ce problème? Le deuxième est qu'il provoque un retard sur mon bouton, bien que je le lance dans un service?

SERVICE

//////////TIMER FUNCTION START////////// 

     private void startTimerClick() { 

      if (stopped) { 
       startTime = System.currentTimeMillis() - elapsedTime; 
      } else { 
       startTime = System.currentTimeMillis(); 
      } 
      mHandler.removeCallbacks(startTimer); 
      mHandler.postDelayed(startTimer, 0); 

     } 

     private void pauseTimerClick() { 
      mHandler.removeCallbacks(startTimer); 
      stopped = true; 

     } 

     private void stopTimerClick() { 
      mHandler.removeCallbacks(startTimer); 
      stopped = false; 

     } 

     private void startTimer() { 

      startTimer = new Runnable() { 
       public void run() { 
        elapsedTime = System.currentTimeMillis() - startTime; 
        updateTimer(elapsedTime); 
        mHandler.postDelayed(this, REFRESH_RATE); 
       } 
      }; 

     } 

     private void updateTimer(float time) { 
      secs = (long) (time/1000); 
      mins = (long) ((time/1000)/60); 
      hrs = (long) (((time/1000)/60)/60); 

      /* 
      * Convert the seconds to String and format to ensure it has a leading 
      * zero when required 
      */ 
      secs = secs % 60; 
      seconds = String.valueOf(secs); 
      if (secs == 0) { 
       seconds = "00"; 
      } 
      if (secs < 10 && secs > 0) { 
       seconds = "0" + seconds; 
      } 

      /* Convert the minutes to String and format the String */ 

      mins = mins % 60; 
      minutes = String.valueOf(mins); 
      if (mins == 0) { 
       minutes = "00"; 
      } 
      if (mins < 10 && mins > 0) { 
       minutes = "0" + minutes; 
      } 

      /* Convert the hours to String and format the String */ 

      hours = String.valueOf(hrs); 
      if (hrs == 0) { 
       hours = "00"; 
      } 
      if (hrs < 10 && hrs > 0) { 
       hours = "0" + hours; 
      } 


     } 
     //////////TIMER FUNCTION END//////////// 


    public String getHours(){ 

     return hours; 
    } 

    public String getMinutes(){ 

     return minutes; 
    } 

    public String getSeconds(){ 

     return seconds; 
    } 
} 

ACTIVITÉ (/ FRAGMENT)

private void timerStart() { 

     handler = new Handler(); 
     Thread t = new Thread() { 

       @Override 
       public void run() { 
       try { 
        while (!isInterrupted()) { 
        Thread.sleep(1000); 
        handler.post(new Runnable() { 
         @Override 
         public void run() { 

          timer.setText(myService.getHours()+":"+myService.getMinutes()+":"+myService.getSeconds()); 
         } 
        }); 
        } 
       } catch (InterruptedException e) { 
       } 
       } 
      }; 

      t.start(); 

    } 

Répondre

0

Vous utilisez des fils aussi bien dans votre service et votre code d'activité/Fragment. L'utilisation de threads pour les tâches sensibles au temps dans Android pose problème car Android peut retarder considérablement les threads.

J'ai utilisé un ScheduledThreadPoolExecutor pour une tâche similaire et cela a très bien fonctionné.

Vous utilisez alors comme ceci:

ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1); // where 1 is the number of needed concurrent threads. 1 should last for your needs. 
executor.scheduleWithFixedDelay(new TimerTask() { 
    // your recurringly executed code here 
}, 0, 1, TimeUnit.SECONDS); 
+0

Serait-il aussi une solution pour sauver l'heure de début dans le service, et de faire le calendrier lui-même seulement dans la principale activité/fragment? @ hoelle2011 –

+0

Je suppose que vous utilisez le service pour garder votre application en vie en arrière-plan. Il est bien sûr possible de conserver l'heure de début dans un membre du service mais peut-être qu'un autre endroit serait plus approprié alors. Si vous avez besoin de la minuterie pour toute autre tâche d'arrière-plan, vous devriez probablement la conserver dans le service. Pensez à des tâches comme la création d'une notification après un certain laps de temps - même lorsque l'interface utilisateur n'est pas visible et que le minuteur de l'activité/fragment peut ne pas s'exécuter. – hoelle2011

Questions connexes