web-dev-qa-db-ja.com

AndroidのStopWatchクラスはすでにありますが、実装が機能しないのはなぜですか?

最近私は http://developer.Android.com/reference/Android/os/CountDownTimer.html を見て、自分のアプリのユーザーに伝えたいので、ストップウォッチ用のそれぞれのクラスがあるかどうか疑問に思いました彼がすでにパズルを解こうとしている時間。このようなストップウォッチを自分でプログラムするのはそれほど複雑ではないということです。私は次のようなことを試みました

_    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            while (true) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                }
                long seconds = (System.currentTimeMillis() - t) / 1000;
                statusBar.setText(String.format("%02d:%02d", seconds / 60, seconds % 60));
            }
        }

    };
    statusBar.post(runnable);
_

しかし、奇妙なことに、アクティビティのonCreateメソッドの最後にこのstatusBar.post(runnable);があるため、アクティビティのレイアウトが膨らむことはありません。つまり、アプリを起動した後、代わりに白い画面しか表示されません。通常のGUI。

クロノメーターを使用する必要があります。

しかしとにかく、UIスレッドからスリープを削除すれば、コードは機能します。

private final Runnable mRunnable = new Runnable() {
    @Override
    public void run() {
        if (mStarted) {
            long seconds = (System.currentTimeMillis() - t) / 1000;
            statusBar.setText(String.format("%02d:%02d", seconds / 60, seconds % 60));
            handler.postDelayed(runnable, 1000L);
        }
    }

};

private Hanlder mHandler;
private boolean mStarted;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mHandler = new Handler();
}

@Override
protected void onStart() {
    super.onStart();
    mStarted = true;
    mHandler.postDealyed(runnable, 1000L);
}

@Override
protected void onStop() {
    super.onStop();
    mStarted = false;
    mHandler.removeCallbacks(mRunnable);
}
6

クロノメーター クラスをご覧ください。

APIDemoのサンプルコード:

import Android.app.Activity;
import Android.os.Bundle;
import Android.os.SystemClock;
import Android.view.View;
import Android.view.View.OnClickListener;
import Android.widget.Button;
import Android.widget.Chronometer;

public class ChronometerDemo extends Activity {
    Chronometer mChronometer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.chronometer);

        Button button;

        mChronometer = (Chronometer) findViewById(R.id.chronometer);

        // Watch for button clicks.
        button = (Button) findViewById(R.id.start);
        button.setOnClickListener(mStartListener);

        button = (Button) findViewById(R.id.stop);
        button.setOnClickListener(mStopListener);

        button = (Button) findViewById(R.id.reset);
        button.setOnClickListener(mResetListener);

        button = (Button) findViewById(R.id.set_format);
        button.setOnClickListener(mSetFormatListener);

        button = (Button) findViewById(R.id.clear_format);
        button.setOnClickListener(mClearFormatListener);
    }

    View.OnClickListener mStartListener = new OnClickListener() {
        public void onClick(View v) {
            mChronometer.start();
        }
    };

    View.OnClickListener mStopListener = new OnClickListener() {
        public void onClick(View v) {
            mChronometer.stop();
        }
    };

    View.OnClickListener mResetListener = new OnClickListener() {
        public void onClick(View v) {
            mChronometer.setBase(SystemClock.elapsedRealtime());
        }
    };

    View.OnClickListener mSetFormatListener = new OnClickListener() {
        public void onClick(View v) {
            mChronometer.setFormat("Formatted time (%s)");
        }
    };

    View.OnClickListener mClearFormatListener = new OnClickListener() {
        public void onClick(View v) {
            mChronometer.setFormat(null);
        }
    };
}

R.layout.chronometer:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android" Android:orientation="vertical" Android:padding="4dip"
    Android:gravity="center_horizontal"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <Chronometer Android:id="@+id/chronometer"
        Android:format="@string/chronometer_initial_format"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_weight="0"
        Android:paddingBottom="30dip"
        Android:paddingTop="30dip"
        />

    <Button Android:id="@+id/start"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content" 
        Android:text="@string/chronometer_start">
        <requestFocus />
    </Button>

    <Button Android:id="@+id/stop"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content" 
        Android:text="@string/chronometer_stop">
    </Button>

    <Button Android:id="@+id/reset"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content" 
        Android:text="@string/chronometer_reset">
    </Button>

    <Button Android:id="@+id/set_format"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content" 
        Android:text="@string/chronometer_set_format">
    </Button>

    <Button Android:id="@+id/clear_format"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content" 
        Android:text="@string/chronometer_clear_format">
    </Button>

</LinearLayout>

これをStrings.xmlに追加します

<string name="chronometer_start">Start</string>
<string name="chronometer_stop">Stop</string>
<string name="chronometer_reset">Reset</string>
<string name="chronometer_set_format">Set format string</string>
<string name="chronometer_clear_format">Clear format string</string>
<string name="chronometer_initial_format">Initial format: <xliff:g id="initial-format">%s</xliff:g></string>
16
Dan

クロノメーター を使用する必要があります。

Chronometer mChronometer;
mChronometer = (Chronometer) findViewById(R.id.chronometer1);
long timeWhenStopped = 0;

クロノメーターを止めると

timeWhenStopped = mChronometer.getBase() - SystemClock.elapsedRealtime(); mChronometer.stop();

それを開始する前にクロノメーター

mChronometer.setBase(SystemClock.elapsedRealtime() + timeWhenStopped); mChronometer.start();

クロノメーターのリセット

mChronometer.setBase(SystemClock.elapsedRealtime()); timeWhenStopped = 0;
3
nzala

コードが機能しない理由は、UIスレッドメッセージキューにRunnableを投稿するためです。ランナブルはwhileループで永久に実行され、UIスレッドがレイアウトの描画や入力への応答などの他のビジネスを実行できないようにします。

UIスレッドでThread.sleep()を使用することは、ほとんどの場合間違っています。代わりにTimerの使用を検討してください。

1
laalto