ユーザーがスタートボタンを押すと、データ収集の機能が開始されるAndroidアプリがあります。このすべてのプロセスにかかった時間を示し、ユーザーが停止を押すまで毎秒更新されるカスタム EditText があります。以下のような AsyncTask を使用してこれを実装しました。
protected class RecTimer extends AsyncTask<Context, Integer, String>
{
@Override
protected String doInBackground( Context... params )
{
int sec=00;
int min=00;
int hours=00;
timerdata=timer.split(":");
hours=Integer.parseInt(timerdata[0]);
min=Integer.parseInt(timerdata[1]);
sec=Integer.parseInt(timerdata[2]);
while(Recording==true)
{
try{
Thread.sleep( 1000 );
publishProgress( sec , min , hours );
sec++;
if(sec==60){
min++;
sec=0;
if(min==60){
hours++;
min=0;
}
}
} catch( Exception e ){
Log.i("makemachine", e.getMessage() );
}
}
return "COMPLETE!";
}
@Override
protected void onPreExecute()
{
Log.i( "makemachine", "onPreExecute()" );
super.onPreExecute();
}
@Override
protected void onProgressUpdate(Integer... values)
{
super.onProgressUpdate(values);
//Log.i( "makemachine", "onProgressUpdate(): " + String.valueOf( values[0] ) );
String format = String.format("%%0%dd", 2);
String Sec = String.format(format, values[0]);
String Min = String.format(format, values[1]);
String Hours = String.format(format, values[2]);
((EditText) findViewById(R.id.duration1)).setText(Hours + ":"+ Min + ":" + Sec);
}
@Override
protected void onPostExecute( String result )
{
super.onPostExecute(result);
Log.i( "makemachine", "onPostExecute(): " + result );
}
}
最初は問題なく動作しているように見えましたが、アプリがアイドル状態でフォーカスが合っていない場合、タイマーが常に適切にカウントされない場合があることがわかりました。たとえば、デバイスを 15 分間放置した後、「時計」で 5 分間しか経過していないことがわかります。ビューがフォーカスに戻ったので、すべてが再び正常に機能しているようです。
そもそもなんでこうなるの?AsyncTask は常にバックグラウンドで実行されるべきではありませんか? これを実装するために使用する必要がある他のより良いアプローチはありますか?
事前にみんなに感謝します!
編集: TrackRuler のおかげで、次のように実装しました。
プライベート Runnable Timer = new Runnable() {
public void run() {
long current = SystemClock.uptimeMillis();
String format = String.format("%%0%dd", 2);
timerdata=timer.split(":");
sec++;
if(sec==60){
min++;
sec=0;
if(min==60){
hours++;
min=0;
}
}
String Sec = String.format(format, sec);
String Min = String.format(format, min);
String Hours = String.format(format, hours);
((EditText) findViewById(R.id.duration1)).setText(Hours + ":"+ Min + ":" + Sec);
TimerHandler.postAtTime(this,
current + 1000);
}
};
私のメイン コードから、ハンドラーから呼び出します: TimerHandler.post(Timer);
今では動作します.Runnable(?)内のビューの更新に問題があるかどうか知りたいだけです