0

PC Java プログラムを Android プラットフォームに移植しようとしています。PC アプリケーションは Swing.Timer を使用して、1 秒ごとに更新をトリガーします。関連付けられたリスナーは、呼び出されると、データベースから新しいデータを取得し、Graphics2D を使用して画面を更新/再描画します。Android のキャンバスを使用して、PC アプリケーションで行うのと同じことを描画する方法を学びました。今、私は Android で同等のタイマーを使用する方法を学ぼうとしています。残念ながら、Android プラットフォームでは物事は単純ではないようです。Timer、Handler、AlarmManager、および AsyncTask があります。AsyncTasks と AlarmManagers は、1 回限りの (負荷の高い?) タスクに適しているように思われます (正しい? 間違っている?)。以下のコードで使用されているアプローチをウェブ上のどこかで見つけて、試してみました。やりたいことができるように思えますが、停止ボタンをクリックするたびに 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 に答える