Java 是否已经有适用于 android 的 StopWatch 类,为什么我的实现不起作用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21981817/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 11:49:10  来源:igfitidea点击:

Is there already a StopWatch class for android and why doesn't my implementation work?

javaandroidtimerrunnablestopwatch

提问by principal-ideal-domain

Lately I saw http://developer.android.com/reference/android/os/CountDownTimer.htmland wondered if there is an respective class for stop watches since I want to tell the user of my App how long he's already trying to solve the puzzle. I mean it isn't that complicated to program such a stop watch on your own. I tried something like

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

But bizarrely the layout of my activity isn't inflated anymore since I have this statusBar.post(runnable);in the end of the acitivity's onCreatemethod meaning that after starting the app I only see a white screen instead of the normal gui.

但奇怪的是,我的活动布局不再膨胀,因为我statusBar.post(runnable);在活动onCreate方法的末尾有这个,这意味着在启动应用程序后,我只看到一个白屏而不是正常的 gui。

采纳答案by Yaroslav Mytkalyk

You should use a Chronometer.

您应该使用天文台。

But anyway, your code can work if you remove the sleep from UI thread.

但无论如何,如果您从 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);
}

回答by laalto

Why your code doesn't work is because you post a Runnableto the UI thread message queue. The runnable runs forever in the whileloop, preventing the UI thread from doing any other business, such as drawing your layout and responding to inputs.

为什么您的代码不起作用是因为您将 a 发布Runnable到 UI 线程消息队列。runnable 在while循环中永远运行,阻止 UI 线程执行任何其他业务,例如绘制布局和响应输入。

Using Thread.sleep()in an UI thread is almost always wrong. Consider using a Timerinstead.

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

回答by Dan

Have a look at the Chronometerclass.

看看Chronometer类。

Sample code from APIDemo:

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

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>

Add this to Strings.xml

将此添加到 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>

回答by nzala

You should use a Chronometer.

您应该使用Chronometer

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

when we stop the chronometer

当我们停止计时

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

the chronometer before starting it

启动前的计时器

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

resetting the chronometer

重置计时器

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