【问题标题】:Android: Stopwatch application crashes due to CalledFromWrongThreadExceptionAndroid:秒表应用程序由于 CalledFromWrongThreadException 而崩溃
【发布时间】:2012-02-10 15:04:40
【问题描述】:

这是我在 Android 上的秒表应用程序代码:

package com.google.labyrinth;

public class Tabalicious extends Activity implements OnClickListener, Runnable
{
    TextView    stopwatchCounter;

    long        startTime, stopTime;

    Thread      stopwatch;
    Button      buttonStart;
    Button      buttonStop;

    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView( R.layout.tabalicious );


        stopwatchCounter    = (TextView) findViewById ( R.id.txtStopwatchCounter );
        buttonStart         = ( Button ) findViewById ( R.id.buttonStart );
        buttonStop          = ( Button ) findViewById ( R.id.buttonStop );

        buttonStart.setOnClickListener( this );

        buttonStop.setOnClickListener( this );
        buttonStop.setEnabled(false);

    }

    public void onClick(View viewClicked)
    {

        switch( viewClicked.getId() )
        {
        case R.id.buttonStart:

            this.buttonStart.setEnabled(false);
            this.buttonStop.setEnabled(true);

            this.startTime = System.currentTimeMillis();

            stopwatch = new Thread(this);
            stopwatch.start();

            break;

        case R.id.buttonStop:

                this.buttonStop.setEnabled(false);
                this.buttonStart.setEnabled(true);

            try {
                stopwatch.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            break;


        }

    }

    public void run()
    {
                    //Update after 5 seconds.
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {

                e.printStackTrace();
            }

            this.stopTime = System.currentTimeMillis();
            this.stopwatchCounter.setText( String.valueOf( (this.stopTime - this.startTime) ) ); //<- Debugger Info: This line is at the top of the call stack.
    }

}

问题是,当我运行应用程序时,我得到一个 CalledFromWrongThread 异常:

02-10 19:53:32.835:E/AndroidRuntime(18482):致命异常: 线程 10 02-10 19:53:32.835:E/AndroidRuntime(18482):

android.view.ViewRoot$CalledFromWrongThreadException: 只有 创建视图层次结构的原始线程可以触及其视图。 02-10 19:53:32.835: E/AndroidRuntime(18482):

在 android.view.ViewRoot.checkThread(ViewRoot.java:3092) 02-10 19:53:32.835: E/AndroidRuntime(18482):

在 android.view.ViewRoot.invalidateChild(ViewRoot.java:677) 02-10 19:53:32.835: E/AndroidRuntime(18482):

在 android.view.ViewRoot.invalidateChildInParent(ViewRoot.java:703) 02-10 19:53:32.835: E/AndroidRuntime(18482):

在 android.view.ViewGroup.invalidateChild(ViewGroup.java:2597) 02-10 19:53:32.835: E/AndroidRuntime(18482):

在 android.view.View.invalidate(View.java:5326) 02-10 19:53:32.835: E/AndroidRuntime(18482):

在 android.widget.TextView.checkForRelayout(TextView.java:5761) 02-10 19:53:32.835: E/AndroidRuntime(18482):

在 android.widget.TextView.setText(TextView.java:2814) 02-10 19:53:32.835: E/AndroidRuntime(18482):

在 android.widget.TextView.setText(TextView.java:2682) 02-10 19:53:32.835: E/AndroidRuntime(18482):

在 android.widget.TextView.setText(TextView.java:2657) 02-10 19:53:32.835:E/AndroidRuntime(18482):在 com.google.labyrinth.Tabalicious.run(Tabalicious.java:144) 02-10 19:53:32.835:E/AndroidRuntime(18482):在 java.lang.Thread.run(Thread.java:1027)

我不太清楚发生了什么。我会很感激你的帮助。谢谢!

【问题讨论】:

    标签: android stopwatch thread-sleep


    【解决方案1】:

    您正在尝试编辑 UI 元素,但您不在 UI 线程上。在 Android 中,UI 元素只能由 UI 线程编辑。在另一个线程上进行计算后更新 UI 元素的方法有很多,包括调用 runOnUiThread() 方法、使用 Handler 或覆盖 AsyncTask 的 PostExecute() 方法。

    【讨论】:

    • 好的,所以我没有创建线程,而是调用了 this.runOnUIThread(this),其中运行方法如下:public void run(){ while(isRunning){this.stopTime = System.currentTimeMillis();Tabalicious.this.stopwatchCounter.setText( String.valueOf( (Tabalicious.this.stopTime - Tabalicious.this.startTime) ) );}} 并且我的应用程序无法响应。只在 UI 线程上运行 setText() 方法会更好还是我做错了什么?
    • @W.K.S Android 中的 UIThread 处理所有屏幕绘制和输入事件。因此,当您在其上放置一个 while(isRunning) 循环时,您将阻止所有 UI 事件,因为它一直在运行您的循环。这就是您遇到无响应错误的原因。您不应该在 UIThread 上运行任何计算,只需在必要时更新视图。将计时器保持在单独的线程中,并且仅在更新 TextView 时调用 runOnUiThread。
    【解决方案2】:

    这只是因为你这样做了:

    this.stopwatchCounter.setText(String.valueOf((this.stopTime - this.startTime)));

    在秒表线程内,您无法触摸视图,因为它不是 UIThread。

    【讨论】:

      猜你喜欢
      • 2018-03-22
      • 2021-04-20
      • 2016-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多