Android计时器泄漏

时间:2013-02-14 18:20:58

标签: android

在我的应用程序中,我试图从可能的多个触摸位置发出粒子。

我有一个用于存储点和相关计时器的类:

private static class Touch
{
    public Timer timer = new Timer();
    public vec position = new vec();
}

在onTouchEvent中,如果是MotionEvent.ACTION_POINTER_DOWN,我实例化一个新的Touch:

Touch t = new Touch();
t.position = new vec(event.getX(id), event.getY(id));
t.timer.scheduleAtFixedRate(new TimeredTouchTask(t.position, id), 0, SHOOTING_INTERVAL);

并将其存储在地图中,使用触摸ID作为键。

如果触发MotionEvent.ACTION_POINTER_UP,我会通过调用计时器上的cancel()并将其从地图中删除来删除触摸。

最后,如果事件的类型为MotionEvent.ACTION_MOVE,我只需迭代地图中的所有Touch实例并更新矢量坐标。

这样可行,但有时定时器不会被正确移除,有时它们会无所事事地保持活力,有时即使我不再触摸屏幕,它们仍会继续拍摄粒子。

我怎样才能使这段代码更加健壮,以便它始终能正常运行?

edit1:ACTION_POINTER_UP的代码

我称这种方法为

private void removeTouch(int id)
{
    Touch t = _touch.get(id);

    if(t != null)
    {
        if(t.timer != null)
        {
            t.timer.cancel();
            t.timer = null;
        }

        t = null;
        _touch.remove(id);
    }
}

edit2:完整列表LINK

通过检查一些日志我发现了例如: 触摸手指#1 触摸手指#2 触摸手指#3 释放手指#3 释放手指#2 释放手指#1

没关系,但正在做:

触摸手指#1 触摸手指#2 触摸手指#3 释放手指#1 释放手指#2 释放手指#3

泄漏了最后一个计时器。我想我肯定会搞砸id和索引。

1 个答案:

答案 0 :(得分:1)

根据您对getX(id)等的使用情况,我猜测id是指针 index ,而不是指针 id 。指针索引不能保证在触摸事件中保持持久性,因此当您将其用于以后的事件时,可能无法找到相同的计时器。

您应该使用指针ID来跟踪哪个是哪个。 getPointerId()会为您提供每个索引。

如果您还没有阅读,我强烈建议您在Android博客上阅读Making Sense of Multitouch