Android Chronometer,保留时间状态(并在后台继续计数)

时间:2011-10-07 01:04:18

标签: android android-activity android-service android-lifecycle chronometer

我有一个计时器,从用户遇到该活动开始计算

我目前在onCreate期间使用计时器设置(最初仅在满足某些条件时启动)。但我需要计时器继续向上计数,直到应用程序及其所有视图都关闭(我有一个“退出”功能)。

问题在于,每当我查看另一个标签并返回其活动时,计时器会重置为零。 (这与oncreate有关,但我不知道它的方式)

我没有找到一种直观的方法来自行保存天文台的状态或计数(或者可能跟踪我自己的时间并在不同的时间点直观地更新天文台)

我的一个想法是使用服务启动Chronometer并让服务继续计数,同时使用计时器的当前时间计数器作为字符串在现有活动更新中使用textview

对此问题的已知方法的任何见解表示赞赏!

这更复杂,因为这是tabhost中的一个活动,每次加载视图时tabhosts都会调用onPause和onResume,这会破坏生命周期函数。

5 个答案:

答案 0 :(得分:6)

有很多方法可以保持时间。我发现的最简单的方法是将时间存储在用于通过getIntent().putExtra("START_TIME", floatvalue)创建原始活动的Intent中。您可以使用getIntent().getFloatExtra("START_TIME", 0f)检索该值。这样做有很多好处:

  • 它不会破坏活动生命周期,也不需要上下文。
  • 可以在其他活动和应用程序之间轻松传递。
  • 它在Pauses and Stops中持续存在。
  • 它不需要特殊的听众。
  • 它不会创建任何新对象(Intent是第一次用于创建Activity的对象。)

此解决方案非常适合持久保存在选项卡式活动中,或跨越对话框等。如果将应用程序留给内存更密集的应用程序,则会有一些限制,但前提是您的活动被销毁(由于内存)。

答案 1 :(得分:5)

由于我的Tabhost,无法依赖生命周期功能。

我所做的是让计时器在中心类中成为静态全局,并在我的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());
    }

答案 2 :(得分:4)

当您切换到其他活动时,前一个活动暂停(onPause,as,依此类推,在附加图像中)当您返回活动时它会恢复,但偶尔当dalvik内存不足时您的Activity对象可以是吨显示时删除。

如果您将应用程序数据保留在Activity实例中,可能会意外丢失它,请阅读此活动生命周期http://developer.android.com/reference/android/app/Activity.html

enter image description here

答案 3 :(得分:4)

这种方法经过测试,效果非常好。 试试这个:

取一个布尔volatile变量来控制你的线程(开始/停止)。获取三个文本视图,小时,分钟和秒文本视图,并完全删除计时器。使用Handler更新UI。编写以下代码。

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是一个布尔volatile变量。将其设置为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()。要停止它,只需执行continueThread = false。要再次启动该线程,请将continueThread设置为true并再次调用timeUpdate()。确保在启动/停止计时器时相应地更新计数器。

答案 4 :(得分:3)

您可以将开始时间保存在共享偏好(或文件等)中,并在onResume()中建立您的计数(而不是从0开始)。

您的UI可能需要进行一些更改才能处理您必须重置开始时间的事实,因为它理论上可以永远计算。