安卓系统中是否已经有了一个StopWatch类,为什么我的实现不起作用?

14

最近我看到了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。


正确的做法是使用一个定时器。 - Merlevede
你不能让主线程进入睡眠状态。如果你在其他线程中运行此代码,你需要一个处理程序才能写入UI(只有主线程可以更改UI)。 - Rudolf Real
3个回答

18

可以查看Chronometer类。

来自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>

3
如果您也发布一个UI截图,那不是更好吗 :) - AZ_
字符串 chronometer_initial_format 缺失,请您在本回答中添加它,这样我们就可以避免去 Google 查看格式了。 - Rudolf Real

7

你应该使用计时器(Chronometer)。

但是无论如何,如果从UI线程中移除sleep,你的代码可以工作。

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);
}

只有 OP 知道,我一开始就修改了他的代码。 - Yaroslav Mytkalyk
计时器不支持暂停和恢复,而秒表需要这个功能。 - Jack

1
你的代码不能正常工作,原因是你将一个Runnable对象发布到了UI线程消息队列中,while循环中的该对象会一直运行,阻塞UI线程无法处理其他任务,比如绘制布局和响应输入事件。

在UI线程中使用Thread.sleep()几乎总是错误的。考虑使用Timer代替。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接