安卓定时器泄露

标签 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);

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

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

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

这行得通,但有时计时器无法正确移除,有时它们保持 Activity 状态什么都不做,有时即使我停止触摸屏幕它们也会继续实际发射粒子。

我怎样才能使这段代码更健壮,使其始终正确运行?

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 和索引。

最佳答案

从你对 getX(id) 等的使用来看,我猜 id 是指针 index,而不是指针 < em>id。不能保证指针索引在触摸事件中保持持久,因此当您将它用于以后的事件时,您可能找不到相同的计时器。

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

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

关于安卓定时器泄露,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14881462/

相关文章:

java - 当我在 Activity 中调用构造函数时应用程序崩溃

android - 删除 Jetpack Compose 中的 LazyColumn 过度滚动效果

android - 仅在 INTEGER PRIMARY KEY 上允许使用 AUTOINCREMENT - android

android - 即使传感器读数没有变化,也会调用 OnSensorChanged

android - 如何使用 QML 在 iOS 和 Android 上 [以正确的方式] 显示网页内容

android - 如何在滚动 tablayout android 时滚动整个 Activity

android - java.lang.NoClassDefFoundError : butterknife. 黄油刀

c# - JSON 字节数组值在 Web 服务中更改

android - 如何修复 com.android.builder.internal.aapt.AaptException : Failed to crunch file?

android - 数据库修剪策略