私はこの件についてよく読んで、完全に混乱してしまいました。私は、RunKeeper などのワークアウト トラッカー アプリを実行しています。これは、ユーザーが実行した時間と距離を追跡します。私はこの「ワークアウト」のメイン インターフェイスをプログラミング中です。このインターフェイスは、毎秒更新される時間を示すタイマーと、これまでの走行距離を示すカウンターの両方を含むストップウォッチのようなレイアウトを示しています。
私の問題は、インターフェースを更新することです。時間を追跡するストップウォッチ クラスがあり、GPS の位置に基づいて距離を計算しますが、固定時間レートで UI を更新する連続スレッドをバックグラウンドで実行するための推奨される方法を見つけるのに途方に暮れています.
私が知る限り、Activity クラスに Handler.Callback インターフェイスを実装するか、Thread と一緒に別の Callback オブジェクトを用意する必要がありますが、どうやって取得するか途方に暮れていますすべてが連携します。ストップウォッチ クラスから取得した表示時間 (単純な開始/終了時間の計算で、スレッドに関連するものは何もありません) と、onLocationChanged() で受け取った位置に基づいて計算された距離の両方を更新する必要があります。
これが私のActivityコードの簡素化されたバージョンです:
public class WorkoutActivity extends Activity implements OnClickListener, LocationListener
{
private LocationManager locManager;
private boolean workoutStarted = false;
// The TextViews to update
private TextView timeLabel;
private TextView distanceLabel;
private Stopwatch stopwatch;
@Override
public void onCreate(Bundle savedInstanceState)
{
/*
... Interface initialisation
*/
stopwatch = new Stopwatch();
}
private void startWorkout() {/* ...*/}
private void stopWorkout() {/* ...*/}
private void pauseWorkout() {/* ...*/}
private void resumeWorkout(){/* ...*/}
public void onClick(View v) {/* ...*/}
public void onLocationChanged(Location location){/* ...*/}
}
ここで読んだほとんどの回答によると、handleMessage メソッドを拡張する Handler オブジェクトを使用する必要がありますが、最近 (少なくとも Lint の警告によると)、メモリ リークを避けるために、そのようなオブジェクトを静的にする必要があります。ただし、アクティビティ クラス内の他のプライベート オブジェクトに Handler 内から直接アクセスして変更するのは少し奇妙です。Handler を拡張するクラスのパラメーターに影響を与えるために必要なオブジェクトを作成することでこれを解決できると思いますが、ちょっと「ハック」のように感じます (WorkoutActivity 内のネストされたクラス):
static class TimeHandler extends Handler
{
static final int MSG_START_TIMER = 1;
static final int MSG_UPDATE_TIMER = 2;
static final int MSG_STOP_TIMER = 3;
private static final int REFRESH_RATE = 1000;
private Stopwatch stopwatch;
private TextView timeLabel;
public TimeHandler(Stopwatch stopwatch, TextView label)
{
this.stopwatch = stopwatch;
this.timeLabel = label;
}
@Override
public void handleMessage(Message msg)
{
super.handleMessage(msg);
switch(msg.what)
{
case MSG_START_TIMER:
stopwatch.start();
this.sendEmptyMessage(MSG_UPDATE_TIMER);
break;
case MSG_UPDATE_TIMER:
timeLabel.setText(stopwatch.getElapsedTimeString());
this.sendEmptyMessageDelayed(MSG_UPDATE_TIMER, REFRESH_RATE);
break;
case MSG_STOP_TIMER:
this.removeMessages(MSG_UPDATE_TIMER);
stopwatch.stop();
timeLabel.setText(stopwatch.getElapsedTimeString());
break;
}
}
では、継続的なバックグラウンド スレッドから UI を更新する「標準的な」方法を誰か説明してもらえますか? ああ、長い質問で申し訳ありません。徹底したかっただけです。