外部类的本地字段不受Runnable代码的影响

时间:2017-01-31 20:14:38

标签: java android multithreading

这最近一直在杀我。我正在制作一个快速设置磁贴,它应该显示为活动或非活动状态,具体取决于它是否可以通过套接字与特定计算机进行通信。以下是我的声明:

public class WakeUpTileService extends TileService {
    private static volatile boolean online;
    private final TimerTask timerTask;
    private Timer timer;

这是构造函数:

public WakeUpTileService() {
    super();
    online = true;
    timer = new Timer();
    timerTask = new TimerTask() {
        @Override
        public void run() {
            boolean shouldBeOn = false;
            try {
                Socket s = new Socket();

                // 3000 is the timeout in milliseconds.
                s.connect(myInetSocketAddress, 3000);

                // Connection was successfully established.
                s.close();
                shouldBeOn = true;
            } catch (Exception e) {
                // Connection failed.
                // shouldBeOn is already false.
            } finally {
                if (shouldBeOn != WakeUpTileService.online) {
                    WakeUpTileService.online = shouldBeOn;

                    // This method causes onStartListening() to be called
                    // on the main thread so I can update the Tile.
                    requestListeningState(
                        getApplicationContext(),
                        new ComponentName(
                            getApplicationContext(),
                            WakeUpTileService.class
                        )
                    );
                }
            }
        }
    };
}

这是计时器启动的地方:

@Override
public void onTileAdded() {
    super.onTileAdded();
    timer.scheduleAtFixedRate(timerTask, 0, 60000);
    // At the moment I have it checking once per minute
    // For debugging purposes. I plan to make it less frequent.
}

这是使用online的值来更新Tile的代码。这会在WakeUpTileService.online = shouldBeOn;中的TimerTask之后在主线程上调用。

@Override
public void onStartListening() {
    Tile t = getQsTile();
    if(WakeUpTileService.online)
        t.setState(Tile.STATE_ACTIVE);
    else
        t.setState(Tile.STATE_INACTIVE);
    t.updateTile();
}

当我逐步调试调试器中的代码时,TimerTask代码肯定在onStartListening被调用之前完成,并且在TimerTask的上下文中,online成立正确的价值。然后,当onStartListening被调用时,online似乎恢复到它在开头时的值。

我已经了解了可能发生的事情:

  • WakeUpTileService中引用的online在某种程度上与Runnable代码中引用的对象不同(这就是为什么我使online静态并使用WakeUpTileService.online代替只是online。)

  • online读取online之前,实际上没有发生onStartListening()的分配。再次,当我使用调试器执行代码时,这似乎没有发生,只是通过查看下面的代码,这似乎不合理。

我不知道这里还会发生什么。请帮忙!

更新:korolar建议这两个类可能已被不同的类加载器加载,经过一些调查后,我发现的原因。我的服务由dalvik.system.PathClassLoader加载,java.util.Timer正在加载java.lang.BootClassLoader。但是,我不知道如何解决或解决这个问题。任何人都可以提供一些建议吗?

1 个答案:

答案 0 :(得分:0)

如果有其他人遇到这个问题,我会告诉你我最终做了什么来修复它。

在Android编程中,显然使用java.util.Timer类通常是不好的做法。相反,我使用Android AlarmManager类和IntentService重写了我的程序。这完全绕过了类加载器问题。