java.lang.IllegalStateException: TimerTask is scheduled already: 合理使用Android中的Timer和TimerTask

7
我正在编写一个连接到服务器并发送ping命令的应用程序,服务器将以pong命令回答。
我想实现连接超时机制,我的想法如下:
  • 客户端发送ping并启动带有定时任务和延迟的计时器
  • 当客户端接收到pong时,计时器任务将被取消。
此外,我想优化内存。因此,不要在每次发送ping命令时重新创建TimerTask。我尝试了以下代码:
private final Timer mSystemLogoutTimer = new Timer();
private final TimerTask mLogoutTask = new TimerTask() {

    @Override
    public void run() {
        mMessageInterface.onConnectionTimeout();
        cancel();
    }
};

private void ping() {
    sendRequest(RequestBuilder.formPing());
    mSystemLogoutTimer.schedule(mLogoutTask, CoreConst.PING_ANSWER_DELAY);
}

private void onPong() {
    mLogoutTask.cancel();
}

但是当我尝试第二次安排TimerTask时,会出现以下错误:
java.lang.IllegalStateException: TimerTask is scheduled already
at java.util.Timer.scheduleImpl(Timer.java:572)
at java.util.Timer.schedule(Timer.java:459)

我不理解,因为我在TimerTask上调用了cancel()方法。

请告诉我我做错了什么。 谢谢回答!


mLogoutTask.cancel(); 返回什么?另外,您尝试过不使用“内存优化”吗? - Shlublu
第一次返回真,第二次返回假。 - Artem Mostyaev
没有“内存优化”,所有工作都正常,cancel始终返回true。 - Artem Mostyaev
好的,我想这已经足够确定正在发生什么了(请参见下文)。 - Shlublu
1个回答

12

TimerTask.cancel() 并不一定能够阻止任务的执行。根据 SDK 文档,仅在实际阻止了任务的执行时返回 true,否则返回 false

看起来你的代码发生了这种情况,第一次返回了 true,但第二次没有返回,因此,在调用 Timer.schedule() 时抛出了 IllegalStateException 异常。

应该检查 TimerTask.cancel() 的返回值,并在返回 false 时重新创建 TimerTask:此时的 TimerTask 已经失效,无法再次使用。


好的,谢谢!尝试为Android编写内存优化的代码失败了 :) - Artem Mostyaev
你认为,启动timertask来检测ping超时是正确的吗? - Artem Mostyaev
2
关于优化,这取决于情况:有时候一些内存优化确实非常有用。但是首先拥有一个能够工作的东西(即使是原型),然后尝试以尽可能少的CPU或内存资源消耗的方式实现它是一个好习惯。前提是收益是相关的。例如,没有必要花费数天时间来获得每次用户填写表单时2毫秒的收益。关于ping超时设计,我无话可说,因为我不太了解上下文。 - Shlublu
1
感谢您的解释,我同意您的观点。让我们结束这个讨论 :) 再次感谢! - Artem Mostyaev

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