6

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

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

问题是每次我查看另一个选项卡并返回其活动时,Chronometer 都会重置为零。(这与oncreate有关,但我不知道如何解决)

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

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

对此问题的已知方法的任何见解将不胜感激!

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

4

5 回答 5

6

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

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

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

于 2011-10-11T23:53:09.207 回答
6

由于我的 Tabhost,无法依赖生命周期函数。

我所做的是使计时器成为中央类中的静态全局,并ontabchangedlistener在我的 tabhost 中添加了一个用于检查被更改为的选项卡是否是带有计时器的选项卡。如果这是真的,那么它将存储计时器当前时间的 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());
    }
于 2011-10-14T03:00:02.777 回答
4

当您切换到不同的活动时,前一个活动被暂停(onPause,asand 等等,在附件中),当您回到活动时,它会恢复,但偶尔当 dalvik 内存不足时,您的 Activity 对象可以在 ton 时被删除显示。

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

在此处输入图像描述

于 2011-10-11T15:39:01.207 回答
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 是一个布尔易失变量。将其设置为 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()。确保在启动/停止计时器时相应地更新计数器。

于 2011-10-14T12:23:51.373 回答
3

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

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

于 2011-10-11T16:19:21.380 回答