Android Chronometer, сохраняет состояние времени (и продолжает считать в фоновом режиме) - PullRequest
5 голосов
/ 07 октября 2011

У меня есть таймер, который отсчитывает время с момента, когда пользователь сталкивается с этой активностью

В настоящее время я использую Chronometer, установленный во время onCreate (первоначально запускаемый только при соблюдении определенных условий). Но мне нужно, чтобы хронометр продолжал считать вверх, пока приложение и все его представления не будут закрыты (для этого у меня есть функция «Выход»).

Проблема в том, что хронометр сбрасывается в ноль каждый раз, когда я смотрю на другую вкладку и возвращаюсь к ее активности. (Это связано с созданием, но я не знаю, как это сделать)

Я не нашел интуитивно понятного способа сохранить состояние или счетчик хронометра в фоновом режиме самостоятельно (или, возможно, самостоятельно отслеживать время и визуально обновлять хронометр в другой момент времени)

У меня была идея запустить хронометр с сервисом и позволить сервису продолжать отсчет, сохраняя при этом текстовое представление в текущем обновлении активности, используя текущее время хронометра в виде строки

Любое понимание известного подхода к этой проблеме приветствуется!

Это еще более усложняется, потому что это действие в tabhost, и tabhosts вызывает onPause и onResume каждый раз, когда вы загружаете представление, поэтому это нарушает функции жизненного цикла.

Ответы [ 5 ]

6 голосов
/ 12 октября 2011

Есть несколько способов сохранить время.Самый простой способ, который я нашел, - сохранить время в Intent, которое использовалось для создания исходного действия, с помощью getIntent().putExtra("START_TIME", floatvalue).Вы можете получить значение с помощью getIntent().getFloatExtra("START_TIME", 0f).Такое выполнение имеет ряд преимуществ:

  • Это не нарушает жизненный цикл Activity и не требует контекста.
  • Его можно легко передавать между другими действиями и приложениями..
  • Он сохраняется среди пауз и остановок.
  • Не требует специальных слушателей.
  • Он не создает никаких новых объектов (намерение используется длясоздать действие в первый раз).

Это решение отлично подходит для сохранения в активности с вкладками или в диалоговых окнах и т. д. У него есть некоторые ограничения, если оставить приложение более ресурсоемким, нотолько если ваша активность уничтожена (из-за памяти).

5 голосов
/ 14 октября 2011

Из-за моего Tabhost на функции жизненного цикла нельзя было положиться.

Я сделал хронологический статический глобальный элемент в центральном классе и добавил ontabchangedlistener в моем вкладке, который проверял, была ли изменена вкладка на вкладку с хронометром. Если это так, то в нем хранится значение Long текущего времени хронометра.

 tabHost.setOnTabChangedListener(new OnTabChangeListener(){

        @Override
        public void onTabChanged(String arg0) {
            // TODO Auto-generated method stub
            if(arg0.contentEquals("homeGroup"))
            {
                //store time in centralhelper.java
                                    //stopWatch is of type Chronometer
                                    //stopWatchLastTime is of type Long and is initially set to zero. Chronometer uses milliseconds to determine time, will never be zero after set
                CentralHelper.stopWatchLastTime = CentralHelper.stopWatch.getBase();
            }
        }

    });

Когда мое представление homeGroup загружается, вызывается функция onResume (), здесь есть условие для получения времени, с которого хронометр возобновляет отсчет. Несмотря на то, что tabhost будет вызывать как onPause (), так и onResume () при КАЖДОЙ загрузке вне обычных функций жизненного цикла, они по-прежнему вызываются до onCreate ()

   public void onResume(){
    super.onResume();

    //update Chronometer with time stored in tabchangelistener
    if(CentralHelper.stopWatchLastTime!=0)
        CentralHelper.stopWatch.setBase(CentralHelper.stopWatchLastTime);
}

это позволило мне сделать аналогичную проверку в onCreate ()

    if(CentralHelper.stopWatchLastTime!=0)
    {

        CentralHelper.stopWatch.start(); //this is where it resumes counting from the base set in onResume()
    }
    else
    {
        CentralHelper.stopWatch.start();
        CentralHelper.stopWatch.setBase(SystemClock.elapsedRealtime());
    }
4 голосов
/ 14 октября 2011

Этот подход проверен и работает очень хорошо.Попробуйте это:

Возьмите логическую переменную volatile, которая будет управлять вашим потоком (запуск / остановка).Возьмите три вида текста, часы, минуты и секунды, и полностью удалите хронометр.Обновите свой пользовательский интерфейс, используя Handler. Напишите следующий код.

public void timeUpdate()
{
    timerThread = new Thread(new Runnable() {

        @Override
        public void run() {
            while(continueThread){
                Date newDate = new Date();
                if(((newDate.getTime()) - date.getTime()) > 1000){
                    secondCounter = secondCounter+1;
                    mHandlerUpdateSec.post(mUpdateSec);
                    System.out.println("Inside the Theread ..."+secondCounter);
                    if(secondCounter > 59){
                        minuteCounter = minuteCounter + 1;
                        mHandlerUpdateMinute.post(mUpdateMinute);
                        secondCounter = 0;
                        if(minuteCounter > 59){
                            hourCounter = hourCounter + 1;
                            mHandlerUpdateHour.post(mUpdateHour);
                            minuteCounter = 0;
                        }
                    }
                }
                try{
                    timerThread.sleep(1000);
                }catch (Exception e) {
                    // TODO: handle exception
                }
            }
        }
    });
    timerThread.start();
}

continueThread - логическая переменная с переменным значением.Установка в false остановит поток.TimerThread является экземпляром потока.Есть три счетчика, счетчики часов, минут и секунд, которые предоставят вам самые последние значения времени.Обработчики обновляются следующим образом.

final Handler mHandlerUpdateSec = new Handler();
final Runnable mUpdateSec = new Runnable() {
    public void run() {
        String temp = "" + secondCounter;
        System.out.println("Temp second counter length: " + temp.length());
        if(temp.length() == 1)
            secTextView.setText("0" + secondCounter);
        else
            secTextView.setText("" + secondCounter);
    }
};
final Handler mHandlerUpdateMinute = new Handler();
final Runnable mUpdateMinute= new Runnable() {
    public void run() {
        String temp = "" + minuteCounter;
        System.out.println("Temp second counter length: " + temp.length());
        if(temp.length() == 1)
            minTextView.setText("0" + minuteCounter);
        else
            minTextView.setText("" + minuteCounter);
    }
};
final Handler mHandlerUpdateHour = new Handler();
final Runnable mUpdateHour = new Runnable() {
    public void run() {
        String temp = "" + hourCounter;
        System.out.println("Temp second counter length: " + temp.length());
        if(temp.length() == 1)
            hourTextView.setText("0" + hourCounter);
        else
            hourTextView.setText("" + hourCounter);
    }
};

Теперь, когда вы хотите запустить таймер, установите continueThread в true и вызовите timeUpdate ().Чтобы остановить это, просто продолжитеThread = false.Чтобы снова запустить поток, установите continueThread равным true и снова вызовите timeUpdate ().Убедитесь, что вы обновили счетчики соответствующим образом во время запуска / остановки таймера.

4 голосов
/ 11 октября 2011

Когда вы переключаетесь на другое действие, предыдущее действие приостанавливается (onPause, и так далее, на прикрепленном изображении), когда вы возвращаетесь к действию, оно возобновляется, но иногда, когда dalvik не хватает памяти, ваш объект Activity может бытьудалено, когда отображается тон.

Если вы храните данные своего приложения в экземпляре Activity, то можете случайно их потерять, прочитайте этот жизненный цикл Activity http://developer.android.com/reference/android/app/Activity.html

enter image description here

3 голосов
/ 11 октября 2011

Вы можете сохранить время запуска в общих настройках (или файле и т. Д.) И установить отсчет с этого (а не начиная с 0) в onResume ().

Вашему пользовательскому интерфейсу могут потребоваться некоторыеизменения, учитывающие тот факт, что вам придется сбрасывать время запуска, поскольку теоретически оно может считаться вечным.

...