java.lang.IllegalStateException:已经调度了TimerTask:在Android中合理使用Timer和TimerTask

Art*_*aev 6 android exception timer

我编写了一个连接到服务器的应用程序,并向他发送ping命令,服务器用pong命令回答.

我想实现连接超时机制.我想它将遵循:

  • 客户端使用timertask和delay 发送ping并启动计时器
  • 当客户端收到pong时,timertask被取消.

另外,我想优化内存.所以,每次发送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();
}
Run Code Online (Sandbox Code Playgroud)

但是当我第二次尝试安排TimerTask时出现以下错误:

java.lang.IllegalStateException: TimerTask is scheduled already
at java.util.Timer.scheduleImpl(Timer.java:572)
at java.util.Timer.schedule(Timer.java:459)
Run Code Online (Sandbox Code Playgroud)

我不明白,因为我打电话cancel()给TimerTask.

请告诉我我做错了什么.谢谢你的回答!

Shl*_*blu 11

TimerTask.cancel()不一定会阻止任务的执行.根据SDK文档,它会true在实际阻止执行时返回,false否则返回.

看起来像第一次true返回时你的代码会发生什么,而不是第二次,导致IllegalStateException在之后调用时抛出Timer.schedule().

您应该检查TimerTask.cancel()的返回代码,并重新创建您TimerTaskfalse返回:在TimerTask被烧毁,无法在该阶段被重用.

  • 那么,关于优化它取决于:有时内存优化可能非常有用.但是首先要有一些可行的东西(即使是原型),然后尝试以尽可能少的CPU或内存资源消耗的方式实现它,这是一个好习惯.只要收益是相关的.例如,每次用户填写表单时,没有必要花费数天时间来获得2ms的收益.关于ping timout设计,我没有什么可说的,因为不了解上下文. (2认同)