4

我已经从一个用户遇到Android的天文台表,保留时间状态(并保持在后台计算)

我目前使用天文台的onCreate过程中设置该活动的一次计数的定时器(最初只有当某些启动条件得到满足)。但我需要计时器继续向上计数,直到应用程序及其所有视图都关闭(我有一个“退出”功能来完成此操作)。

问题是,每当我看到另一个选项卡并重新开始活动时,天文台都会重置为零。 (这与oncreate有关,但我不知道周围的方式)

我没有找到一种直观的方式来保存天文台的状态或countup在自己的背景(或可能跟踪在我自己的时间和在不同的时间点更新计时表)

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

任何有关此问题的已知方法的深入了解!

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

回答

4

由于我的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()); 
    } 
4

当您切换到另一个活动时,当您恢复活动时,前一个活动对象会暂停(onPause,等等,在附加图像中),但偶尔当dalvik内存不足时,您的活动对象可以吨显示时删除。

如果你把你的应用程序数据的活动情况下,你可能会不小心失去它,请仔细阅读本活动的生命周期http://developer.android.com/reference/android/app/Activity.html

enter image description here

+0

我对此很熟悉,现在您是否有解决如何坚持天文钟的时间?也许在不同的线程上或者在sharedpreferences中保存时间以后再恢复它的另一种方式 – CQM

+0

通常我会创建一个包含所有运行时变量的单例类。然后添加setter,getters和listeneres到这个值是很容易的,例如一个想要显示当前值的新活动可以在Resume上注册该falure的变化并取消注册onPause,经典的MVC模型 – michael

3

您可以节省启动时间在sharedpreferences(或文件,等等。 )并在onResume()中建立你的计数(而不是从0开始)。

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

+0

这就是我试图做,但我的生命周期功能也发生故障。 (当我离开它时,我的活动会调用onPause(),并且当它恢复时....我甚至尝试了onStop(),并且它被调用两次) – CQM

5

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

  • 它不会中断Activity LifeCycle并且不需要上下文。
  • 它可以轻松地在其他活动和应用程序之间传递。
  • 它在Pause和Stops之间依然存在。
  • 它不需要特殊的监听器。
  • 它不会创建任何新对象(Intent是第一次用于创建活动的对象)。

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

+0

这是我在几个应用程序中使用的一种技术,称为Intent回收。我有一些关于它和周围Intents的其他技术的论文。 –

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()。确保在启动/停止定时器时相应地更新计数器。

+0

这对我没有天文台时会有帮助,谢谢 – CQM

+0

非常好!只是一个快速的改变。当改变全文时,我将if条件改为if(secondCounter <10)[和minuteCounter/hourCounter]。这样你不需要每秒,每分钟和每小时一个新的String和一个新的String.lenght()。我认为这可以大大提升演出水平。此外,我已经调整它使用EventBus,所以我可以从textviews中使用这个unbound。 –

相关问题