0

我正在尝试将 PC Java 程序移植到 Android 平台。PC 应用程序使用 Swing.Timer 每秒触发一次更新。关联的侦听器在被调用时从数据库中获取新数据,然后使用 Graphics2D 更新/重绘屏幕。我已经学会了如何使用 Android 的 Canvas 来绘制与我使用 PC 应用程序相同的东西。现在我正在尝试学习如何在 Android 中使用等效的 Timer。不幸的是,在 Android 平台上,事情似乎并不那么简单。有 Timers、Handlers、AlarmManagers 和 AsyncTasks。似乎 AsyncTasks 和 AlarmManagers 更适合一次性(重型?)任务(对吗?错了?)关于 Timers 和 Handlers,我看到很多帖子说不要使用 Timer,而是使用 Handlers。我在网上某处找到了下面代码中使用的方法并尝试了它。似乎它应该做我想做的事,但是每当我单击停止按钮时它都会挂起 GUI。有谁知道它为什么这样做?

感谢一百万比尔

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    dateFormat = new SimpleDateFormat(dateFormatString);
    mHandler = new Handler();
    mUpdateTimeTask = new MyRunnable();
    Button button = (Button) findViewById(R.id.start_button);
    button.setOnClickListener(new MyStartListener());
    button = (Button) findViewById(R.id.stop_button);
    button.setOnClickListener(new MyStopListener());
}

class MyStartListener implements View.OnClickListener {
    public void onClick(View v) {
        if (startUptimeMillis == 0L) {
            startUptimeMillis = SystemClock.uptimeMillis();
            mHandler.removeCallbacks(mUpdateTimeTask);
            mHandler.postDelayed(mUpdateTimeTask, 100);
        }
    }
};

class MyStopListener implements View.OnClickListener {
    public void onClick(View v) {
        mHandler.removeCallbacks(mUpdateTimeTask);
   }
};

class MyRunnable implements Runnable {
    public void run() {
        final long start = startUptimeMillis;
        long millis = SystemClock.uptimeMillis() - start;
        int seconds = (int) (millis / 1000);
        int minutes = seconds / 60;
        seconds = seconds % 60;
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(System.currentTimeMillis());
        TextView tv = (TextView) findViewById(R.id.time_textView);
        tv.setText(dateFormat.format(calendar.getTime()));
        mHandler.postAtTime(this, (((minutes * 60) + seconds + 1) * 1000));
    }
 };

编辑:问题是 postAtTime 需要一个绝对的开始时间,而不是我的示例使用的延迟。(请参阅此处的 postAtTime)所以我用下面的代码替换了上面的所有时间代码,它做了我想要的!!:

long millis = SystemClock.uptimeMillis();
mHandler.postAtTime(this, millis+1000);
4

1 回答 1

1

我看不出这会如何挂起您的应用程序,除非您的意思是开始按钮不再起作用...也许您想将其添加到停止侦听器中:

public void onClick(View v) {
    startUptimeMillis = 0l; // Reset startUptimeMillis
    mHandler.removeCallbacks(mUpdateTimeTask);
}

至于 Timers、AsyncsTask 等……你是对的,在不久的将来在 Android 中编写事件的最佳方法是使用 Handler 和 Runnable。AlarmManagers 不适用于动画中的快速回调,而 AsyncTasks 更适合重型计算。

我想提供一个更简单的更新 Runnable:

class MyRunnable implements Runnable {
    public void run() {
        // You should make this a class variable and initialize it in onCreate(), 
        //   there is no need to search for the same View every second.
        TextView tv = (TextView) findViewById(R.id.time_textView);

        final long now = System.currentTimeMillis();
        tv.setText(dateFormat.format(now));
        mHandler.postAtTime(this, 1000 - (now - start) % 1000); // Accounts for millisecond offsets over time
        // mHandler.postDelayed(this, 1000); // Effected by minute offsets
    }
};
于 2012-11-14T17:39:01.663 回答