我有一个runnable,每1秒输出一个变量的值。当我启动mainActivity并在后台运行整个应用程序时,runnable启动。
当我关闭应用程序(隐藏状态)并再次启动应用程序时,logcat开始输出更快。每次我这样做都会变得更快。为什么?
@Override
public void onStart()
{
mHandler.postDelayed(myRunnable, 1000);
super.onStart();
}
public Runnable myRunnable = new Runnable()
{
@Override
public void run()
{
count ++;
android.util.Log.w(" SYNC ", "COUNT:"+count);
mHandler.postDelayed(myRunnable, 1000);
}
};
谢谢大家的回答!我会给予信任。然而,是@pskink发布了这个Android Runnable runs faster after Resume,它为我解决了它。
答案 0 :(得分:5)
呼叫 在调用postDelayed
之前removeCallbacksAndMessages(null)答案 1 :(得分:2)
因为每次在隐藏后显示应用程序时,都会调用onStart方法,从而导致在执行相同作业时创建runnable的新实例。
因此,要解决此问题,您需要在onStop方法中停止Runnable。
作为一般经验法则,当覆盖onCreate
onStart
,onResume
,onDestroy
以触发某些连续行为时,您需要在各自的行为中禁用此行为对应方(onStop
,onPause
,public Runnable myRunnable = new Runnable()
{
private boolean stopped = false;
public synchronized void stop() {
stopped = true;
}
public synchronized void reset() {
stopped = false;
}
@Override
public void run()
{
if(stopped) return;
count ++;
android.util.Log.w(" SYNC ", "COUNT:"+count);
mHandler.postDelayed(myRunnable, 1000);
}
};
)。
因此,在您的情况下,禁用onStart(启动新线程)中触发的行为的一种方法是在onStop中停止此线程。例如:
myRunnable.stop()
现在只需在onStop()
方法中调用myRunnable.reset()
即可。如果您要重复使用myRunnable实例,请在onStart()
中调用{{1}}以再次启用它。
答案 2 :(得分:1)
也许这张图片会有所帮助。如果将代码移动到onCreate,则应该没问题。
答案 3 :(得分:1)
试
removeCallbacks(myRunnable)
onPause()中的并在onResume()
中发布回调编辑(包括我对答案的评论):
当您返回活动时,活动实际上是重新创建的,因此您有两个活动:一个显示,一个不可见。并且runnables仍然重新发布自己,每个都有一个隐式指针指向创建它的Activity ...这通常称为泄漏,或活动泄漏。
另请注意,在没有用户交互的情况下运行的代码不应放入Activity中,它应该是一个服务。
此外,如果计数器不是静态的,则在活动离开屏幕后您无法访问它。
从MVC(模型 - 视图 - 控制器)的角度来看,Activity = Controller 。 View 是布局XML中指定的视图层次结构,我们可以创建自己的自定义视图类,但通常我们会重用现有的类。并且模型是屏幕旋转90度后必须存活的(当方向更改时,活动和视图层次结构会重新创建)。 可运行的重新发布逻辑应该属于模型。
答案 4 :(得分:1)
您可以询问onStart()是否已经有一个runnable。如果它为null,则创建新的runnable如果它不为null,则不执行任何操作