在特定时间使用postDelayed运行任务

4

我希望在特定的时间开始一项任务。为此,我使用以下runnablepostDelayed方法:

private Runnable mLaunchTask = new Runnable() {
        public void run() {

            try {
                MY TASK
            } catch (IllegalStateException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
};

在我的代码中,我使用mLunchTask如下:

mHandler = new Handler();
mHandler.postDelayed(mLaunchTask, myDelay*1000); 

并且myDelay的计算方法如下:

s  = DateFormat.format("hh:mm:ss aaa", d.getTime());
cTime = s.toString(); // current Time
ch = Integer.parseInt(cTime.substring(0,2)); // current hour
cm = Integer.parseInt(cTime.substring(3,5)); // current minute
cs = Integer.parseInt(cTime.substring(6,8)); // current second
if (cTime.substring(9,11).equalsIgnoreCase("pm") && (ch<12) ) ch = ch+12; 
myDelay=(desiredHour-ch)*3600+(desiredMinute-cm)*60 - cs;
if (myDelay<0) myDelay = 0;

desiredHourdesiredMinute由用户设置。期望的是MY TASKdesiredHourdesiredMinute以及0秒开始执行。 然而,“MY TASK”会有几秒钟的延迟,看起来是随机的。

基于上述代码,是否存在任何导致它不能在精确的期望时间启动的原因?

谢谢


啊,mLunchTask:我的最爱 :) - Engineer
3个回答

6

首先,你的延迟计算是正确的,但“pm”检测在其他语言中无法工作。最好使用日历来获取延迟时间:

Calendar calendar = Calendar.getInstance();
long currentTimestamp = calendar.getTimeInMillis();
calendar.set(Calendar.HOUR_OF_DAY, desiredHour);
calendar.set(Calendar.MINUTE, desiredMinute);
calendar.set(Calendar.SECOND, 0);
long diffTimestamp = calendar.getTimeInMillis() - currentTimestamp;
long myDelay = (diffTimestamp < 0 ? 0 : diffTimestamp);

现在您已经拥有以毫秒为单位的延迟时间,可以开始处理程序:

new Handler().postDelayed(mLaunchTask, myDelay);

在我的测试中,以下可运行日志在期望时间内无延迟。
private Runnable mLaunchTask = new Runnable() {
    public void run() {
        Calendar calendar = Calendar.getInstance();
        Log.d("test", "started at " 
            + calendar.get(Calendar.HOUR_OF_DAY) + " " 
            + calendar.get(Calendar.MINUTE) + " "
            + calendar.get(Calendar.SECOND)
        );
    }
};

也许您的启动任务需要几秒钟才能加载? < p > AlarmManager 可以是一种替代方案吗?< /p >

谢谢你的回答。我的任务不是很重,我会立即开始。不过,你提出的查看AlarmManager的建议很好,我应该能够使用它。 - TJ1

0
根据我的经验和文档阅读,postDelayed 基于系统启动时间而非真实时间。如果手机进入深度睡眠状态,真实时间会流逝而系统启动时间不会增加。这意味着您的任务将比预期开始得更晚。
Handler 看起来确实是为在活动中更新 GUI 而设计的,而不是为了远期安排任务。正如 scessor 所说,AlarmManager 可能是您最好的选择。

0

Naliba的回答并不完全正确。

根据可以在这里看到的文档,可以看出这个类是专门用于在未来运行任务的。

"Handler有两个主要用途:(1) 安排消息和可运行对象在将来某个时间执行;(2) 将操作排队以在与您自己不同的线程上执行。"

关于系统进入睡眠模式时应用程序的行为没有任何参考,因此在发布其他信息之前应该进行测试。


我的答案是正确的;我们写帖子时,谷歌文档真的很糟糕。他们后来改进了它,通过链接到uptimeMillis的定义来改善它。 - Naliba

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接