安卓定时器泄漏

3
在我的应用程序中,我试图让粒子从可能的多个触摸位置发射。
我有一个用于存储点和关联计时器的类:
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);

将其存储在地图中,使用touch id作为键。
如果触发了MotionEvent.ACTION_POINTER_UP,我会通过在计时器上调用cancel()并从地图中删除它来删除触摸。
最后,如果事件的类型为MotionEvent.ACTION_MOVE,我只需迭代地图中所有Touch实例并更新矢量坐标即可。
这个方法起作用,但有时计时器不会被正确删除,有时它们保持活动状态却什么也不做,有时即使我停止触摸屏幕,它们仍会继续发射粒子。
我该如何使这段代码更加健壮,以便始终能正确运行?
编辑1: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);
    }
}

编辑2:完整列表链接

通过检查一些日志,我发现例如:

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

是可以的,但是执行以下操作:

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

会泄漏最后一个定时器。 我认为我肯定在处理ID和索引。


你能在处理 ACTION_POINTER_UP 事件并取消计时器时发布代码吗? - Matthieu
更新了...可能做得不太好。 - キキジキ
这看起来对我来说都很好...也许最好的方法是添加一些调试打印(带有ID),也许你可以找出一些测试失败的模式(!= null),或者如果取消调用发生但实际上并不起作用... - Matthieu
谢谢,我会尝试找出问题所在。 - キキジキ
1个回答

1
根据您使用的 getX(id) 等内容,我猜测 id 是指针索引,而不是指针 ID。指针索引不能保证在触摸事件之间保持持久性,因此您可能无法在以后的事件中找到相同的计时器。
您应该使用指针 ID 来跟踪它们的位置。getPointerId() 将为每个索引提供指针 ID。
如果您还没有阅读过,请务必阅读 Android 博客上的 Making Sense of Multitouch

我认为我正在使用正确的值。首先,我使用event.getActionIndex()获取索引,然后将id变量分配给event.getPointerId(index)。 - キキジキ
你确定吗?因为 getX() 函数需要使用指针索引而不是 id 值,而你在这里使用了 id 值,并且在下一行中仍然使用相同的 id 来构造你的 TimeredTouchTask()。其中一个看起来似乎并不正确。 - Geobits
文档中写着“index”,但实际上指的是id?关于getX >> “返回给定指针索引的此事件的X坐标(使用getPointerId(int)查找此索引的指针标识符)。整数为像素;对于子像素精确的输入设备,该值可能具有小数。”我不确定,但我的坐标看起来正确。 - キキジキ
文档是正确的,它使用了索引。我已经多次使用过它。您可以在我链接的博客文章中的示例代码中自行查看。我无法说出为什么您的坐标似乎是正确的,但也许如果您发布处理索引/ID的代码,情况会变得清晰明了。 - Geobits
哦,你说得对!我已经编辑了我的问题,并附上了方法代码。 - キキジキ
我想我找到了问题所在!因为我使用了id,在第66/67行编写了一个检查,但实际上它删除了对有效计时器的引用。现在看起来可以工作了。 - キキジキ

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