Есть ли уже класс секундомера для android, и почему моя реализация не работает?
Недавно я видел 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);
Но, как ни странно, план моей деятельности больше не раздувается, так как у меня есть это statusBar.post(runnable);
в конце действия onCreate
метод означает, что после запуска приложения я вижу только белый экран вместо обычного графического интерфейса.
4 ответа:
Вы должны использовать Хронометр.
Но в любом случае, ваш код может работать, если вы удалите спящий режим из потока пользовательского интерфейса.
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); }
Взгляните на класс Хронометр.
Пример кода из 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. макет.хронометр:
<?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>
Добавьте это к строкам.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>
Вы должны использовать Хронометр .
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;
Причина, по которой ваш код не работает, заключается в том, что вы отправляете сообщение
Runnable
в очередь сообщений потока пользовательского интерфейса. Runnable работает вечно в циклеwhile
, не позволяя потоку пользовательского интерфейса выполнять любые другие действия, такие как рисование макета и реагирование на входные данные.Использование
Thread.sleep()
в потоке пользовательского интерфейса почти всегда неправильно. Вместо этого рассмотрите возможность использованияTimer
.