Android - 线程正在破坏应用程序

标签 android multithreading

我创建了一个简单的应用程序。

当用户触摸“开始..”按钮时,它会在按钮标签上显示“加载动画”。

我在我的 PC 上创建了应用程序(例如桌面应用程序),并且运行良好。

Android的应用程序代码:

package com.example.threaddot;
import android.os.Bundle;
import android.app.Activity;
import android.app.AlertDialog;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.TextView;

public class MainActivity extends Activity {

    SeekBar pointSpeed, numPoint;
    Button startButton, detailsButton;
    Thread count;
    boolean started = false;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // my vars
        startButton = (Button) findViewById(R.id.button_start);
        detailsButton = (Button) findViewById(R.id.button_details);
        numPoint = (SeekBar) findViewById(R.id.seekBar_numpoints);
        pointSpeed = (SeekBar) findViewById(R.id.PointSpeedSeekBar);

        count = new Thread(new Runnable() {

            @Override
            public void run() {
                setDots();
            }
        });

        startButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                count.start();
            }
        });

        detailsButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                showAlert("Info",
                        String.format("Current: %s, %d points, and shown per %d m/s.", !started ? "working" : "suspend", 
                                numPoint.getProgress(), pointSpeed.getProgress()));             
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }

    public void setDots() {
        int counter = 0, numPoints = numPoint.getProgress();
        while(true) {
            if(counter++ < 10) {
                startButton.setText(startButton.getText() + ".  ");
            }

            else {
                counter = 0;
            }

            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }           
    }

    void showAlert(String title, String msg) {
        AlertDialog alertDialog;
        alertDialog = new AlertDialog.Builder(this).create();
        alertDialog.setTitle(title);
        alertDialog.setMessage(msg);
        alertDialog.show();
    }
}

当我按下“开始 ..”按钮时,它崩溃了。

换句话说,

startButton.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            count.start();
        }
    });

应用程序崩溃。为什么?

日志:

01-18 20:07:43.453: W/dalvikvm(29186): threadid=10: thread exiting with uncaught exception (group=0x40018578)
01-18 20:07:43.500: E/AndroidRuntime(29186): FATAL EXCEPTION: Thread-11
01-18 20:07:43.500: E/AndroidRuntime(29186): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
01-18 20:07:43.500: E/AndroidRuntime(29186):    at android.view.ViewRoot.checkThread(ViewRoot.java:3055)
01-18 20:07:43.500: E/AndroidRuntime(29186):    at android.view.ViewRoot.invalidateChild(ViewRoot.java:649)
01-18 20:07:43.500: E/AndroidRuntime(29186):    at android.view.ViewRoot.invalidateChildInParent(ViewRoot.java:675)
01-18 20:07:43.500: E/AndroidRuntime(29186):    at android.view.ViewGroup.invalidateChild(ViewGroup.java:2511)
01-18 20:07:43.500: E/AndroidRuntime(29186):    at android.view.View.invalidate(View.java:5279)
01-18 20:07:43.500: E/AndroidRuntime(29186):    at android.widget.TextView.checkForRelayout(TextView.java:5782)
01-18 20:07:43.500: E/AndroidRuntime(29186):    at android.widget.TextView.setText(TextView.java:2824)
01-18 20:07:43.500: E/AndroidRuntime(29186):    at android.widget.TextView.setText(TextView.java:2685)
01-18 20:07:43.500: E/AndroidRuntime(29186):    at android.widget.TextView.setText(TextView.java:2654)
01-18 20:07:43.500: E/AndroidRuntime(29186):    at com.example.threaddot.MainActivity.setDots(MainActivity.java:66)
01-18 20:07:43.500: E/AndroidRuntime(29186):    at com.example.threaddot.MainActivity$1.run(MainActivity.java:32)
01-18 20:07:43.500: E/AndroidRuntime(29186):    at java.lang.Thread.run(Thread.java:1019)
01-18 20:10:49.632: W/ActivityThread(29426): Application com.example.threaddot is waiting for the debugger on port 8100...
01-18 20:10:49.648: I/System.out(29426): Sending WAIT chunk
01-18 20:10:49.859: I/System.out(29426): Debugger has connected
01-18 20:10:49.859: I/System.out(29426): waiting for debugger to settle...
01-18 20:10:50.054: I/System.out(29426): waiting for debugger to settle...
01-18 20:10:50.257: I/System.out(29426): waiting for debugger to settle...
01-18 20:10:50.460: I/System.out(29426): waiting for debugger to settle...
01-18 20:10:50.664: I/System.out(29426): waiting for debugger to settle...
01-18 20:10:50.867: I/System.out(29426): waiting for debugger to settle...
01-18 20:10:51.062: I/System.out(29426): waiting for debugger to settle...
01-18 20:10:51.265: I/System.out(29426): waiting for debugger to settle...
01-18 20:10:51.468: I/System.out(29426): waiting for debugger to settle...
01-18 20:10:51.671: I/System.out(29426): waiting for debugger to settle...
01-18 20:10:51.875: I/System.out(29426): waiting for debugger to settle...
01-18 20:10:52.085: I/System.out(29426): waiting for debugger to settle...
01-18 20:10:52.281: I/System.out(29426): waiting for debugger to settle...
01-18 20:10:52.500: I/System.out(29426): waiting for debugger to settle...
01-18 20:10:52.695: I/System.out(29426): waiting for debugger to settle...
01-18 20:10:52.898: I/System.out(29426): waiting for debugger to settle...
01-18 20:10:53.101: I/System.out(29426): debugger has settled (1476)
01-18 20:12:48.117: W/dalvikvm(29426): threadid=10: thread exiting with uncaught exception (group=0x40018578)
01-18 20:12:48.195: E/AndroidRuntime(29426): FATAL EXCEPTION: Thread-10
01-18 20:12:48.195: E/AndroidRuntime(29426): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
01-18 20:12:48.195: E/AndroidRuntime(29426):    at android.view.ViewRoot.checkThread(ViewRoot.java:3055)
01-18 20:12:48.195: E/AndroidRuntime(29426):    at android.view.ViewRoot.invalidateChild(ViewRoot.java:649)
01-18 20:12:48.195: E/AndroidRuntime(29426):    at android.view.ViewRoot.invalidateChildInParent(ViewRoot.java:675)
01-18 20:12:48.195: E/AndroidRuntime(29426):    at android.view.ViewGroup.invalidateChild(ViewGroup.java:2511)
01-18 20:12:48.195: E/AndroidRuntime(29426):    at android.view.View.invalidate(View.java:5279)
01-18 20:12:48.195: E/AndroidRuntime(29426):    at android.widget.TextView.checkForRelayout(TextView.java:5782)
01-18 20:12:48.195: E/AndroidRuntime(29426):    at android.widget.TextView.setText(TextView.java:2824)
01-18 20:12:48.195: E/AndroidRuntime(29426):    at android.widget.TextView.setText(TextView.java:2685)
01-18 20:12:48.195: E/AndroidRuntime(29426):    at android.widget.TextView.setText(TextView.java:2654)
01-18 20:12:48.195: E/AndroidRuntime(29426):    at com.example.threaddot.MainActivity.setDots(MainActivity.java:66)
01-18 20:12:48.195: E/AndroidRuntime(29426):    at com.example.threaddot.MainActivity$1.run(MainActivity.java:32)
01-18 20:12:48.195: E/AndroidRuntime(29426):    at java.lang.Thread.run(Thread.java:1019)
01-18 20:14:52.031: D/AndroidRuntime(29761): Shutting down VM
01-18 20:14:52.031: W/dalvikvm(29761): threadid=1: thread exiting with uncaught exception (group=0x40018578)
01-18 20:14:52.062: E/AndroidRuntime(29761): FATAL EXCEPTION: main
01-18 20:14:52.062: E/AndroidRuntime(29761): java.lang.IllegalThreadStateException: Thread already started.
01-18 20:14:52.062: E/AndroidRuntime(29761):    at java.lang.Thread.start(Thread.java:1227)
01-18 20:14:52.062: E/AndroidRuntime(29761):    at com.example.threaddot.MainActivity$2.onClick(MainActivity.java:40)
01-18 20:14:52.062: E/AndroidRuntime(29761):    at android.view.View.performClick(View.java:2485)
01-18 20:14:52.062: E/AndroidRuntime(29761):    at android.view.View$PerformClick.run(View.java:9080)
01-18 20:14:52.062: E/AndroidRuntime(29761):    at android.os.Handler.handleCallback(Handler.java:587)
01-18 20:14:52.062: E/AndroidRuntime(29761):    at android.os.Handler.dispatchMessage(Handler.java:92)
01-18 20:14:52.062: E/AndroidRuntime(29761):    at android.os.Looper.loop(Looper.java:130)
01-18 20:14:52.062: E/AndroidRuntime(29761):    at android.app.ActivityThread.main(ActivityThread.java:3687)
01-18 20:14:52.062: E/AndroidRuntime(29761):    at java.lang.reflect.Method.invokeNative(Native Method)
01-18 20:14:52.062: E/AndroidRuntime(29761):    at java.lang.reflect.Method.invoke(Method.java:507)
01-18 20:14:52.062: E/AndroidRuntime(29761):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
01-18 20:14:52.062: E/AndroidRuntime(29761):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
01-18 20:14:52.062: E/AndroidRuntime(29761):    at dalvik.system.NativeStart.main(Native Method)
01-18 20:15:35.492: W/ActivityThread(29953): Application com.example.threaddot is waiting for the debugger on port 8100...
01-18 20:15:35.734: I/System.out(29953): Sending WAIT chunk
01-18 20:15:35.937: I/System.out(29953): Debugger has connected
01-18 20:15:35.937: I/System.out(29953): waiting for debugger to settle...
01-18 20:15:36.140: I/System.out(29953): waiting for debugger to settle...
01-18 20:15:36.343: I/System.out(29953): waiting for debugger to settle...
01-18 20:15:36.546: I/System.out(29953): waiting for debugger to settle...
01-18 20:15:36.742: I/System.out(29953): waiting for debugger to settle...
01-18 20:15:36.945: I/System.out(29953): waiting for debugger to settle...
01-18 20:15:37.148: I/System.out(29953): waiting for debugger to settle...
01-18 20:15:37.359: I/System.out(29953): waiting for debugger to settle...
01-18 20:15:37.554: I/System.out(29953): waiting for debugger to settle...
01-18 20:15:37.757: I/System.out(29953): waiting for debugger to settle...
01-18 20:15:37.960: I/System.out(29953): waiting for debugger to settle...
01-18 20:15:38.164: I/System.out(29953): waiting for debugger to settle...
01-18 20:15:38.367: I/System.out(29953): debugger has settled (1495)
01-18 20:16:13.609: W/dalvikvm(29953): threadid=9: thread exiting with uncaught exception (group=0x40018578)
01-18 20:16:13.679: E/AndroidRuntime(29953): FATAL EXCEPTION: Thread-10
01-18 20:16:13.679: E/AndroidRuntime(29953): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
01-18 20:16:13.679: E/AndroidRuntime(29953):    at android.view.ViewRoot.checkThread(ViewRoot.java:3055)
01-18 20:16:13.679: E/AndroidRuntime(29953):    at android.view.ViewRoot.invalidateChild(ViewRoot.java:649)
01-18 20:16:13.679: E/AndroidRuntime(29953):    at android.view.ViewRoot.invalidateChildInParent(ViewRoot.java:675)
01-18 20:16:13.679: E/AndroidRuntime(29953):    at android.view.ViewGroup.invalidateChild(ViewGroup.java:2511)
01-18 20:16:13.679: E/AndroidRuntime(29953):    at android.view.View.invalidate(View.java:5279)
01-18 20:16:13.679: E/AndroidRuntime(29953):    at android.widget.TextView.checkForRelayout(TextView.java:5782)
01-18 20:16:13.679: E/AndroidRuntime(29953):    at android.widget.TextView.setText(TextView.java:2824)
01-18 20:16:13.679: E/AndroidRuntime(29953):    at android.widget.TextView.setText(TextView.java:2685)
01-18 20:16:13.679: E/AndroidRuntime(29953):    at android.widget.TextView.setText(TextView.java:2654)
01-18 20:16:13.679: E/AndroidRuntime(29953):    at com.example.threaddot.MainActivity.setDots(MainActivity.java:66)
01-18 20:16:13.679: E/AndroidRuntime(29953):    at com.example.threaddot.MainActivity$1.run(MainActivity.java:32)
01-18 20:16:13.679: E/AndroidRuntime(29953):    at java.lang.Thread.run(Thread.java:1019)
01-18 20:21:29.492: D/AndroidRuntime(30489): Shutting down VM
01-18 20:21:29.492: W/dalvikvm(30489): threadid=1: thread exiting with uncaught exception (group=0x40018578)
01-18 20:21:29.632: E/AndroidRuntime(30489): FATAL EXCEPTION: main
01-18 20:21:29.632: E/AndroidRuntime(30489): java.lang.IllegalThreadStateException: Thread already started.
01-18 20:21:29.632: E/AndroidRuntime(30489):    at java.lang.Thread.start(Thread.java:1227)
01-18 20:21:29.632: E/AndroidRuntime(30489):    at com.example.threaddot.MainActivity$2.onClick(MainActivity.java:40)
01-18 20:21:29.632: E/AndroidRuntime(30489):    at android.view.View.performClick(View.java:2485)
01-18 20:21:29.632: E/AndroidRuntime(30489):    at android.view.View$PerformClick.run(View.java:9080)
01-18 20:21:29.632: E/AndroidRuntime(30489):    at android.os.Handler.handleCallback(Handler.java:587)
01-18 20:21:29.632: E/AndroidRuntime(30489):    at android.os.Handler.dispatchMessage(Handler.java:92)
01-18 20:21:29.632: E/AndroidRuntime(30489):    at android.os.Looper.loop(Looper.java:130)
01-18 20:21:29.632: E/AndroidRuntime(30489):    at android.app.ActivityThread.main(ActivityThread.java:3687)
01-18 20:21:29.632: E/AndroidRuntime(30489):    at java.lang.reflect.Method.invokeNative(Native Method)
01-18 20:21:29.632: E/AndroidRuntime(30489):    at java.lang.reflect.Method.invoke(Method.java:507)
01-18 20:21:29.632: E/AndroidRuntime(30489):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
01-18 20:21:29.632: E/AndroidRuntime(30489):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
01-18 20:21:29.632: E/AndroidRuntime(30489):    at dalvik.system.NativeStart.main(Native Method)

最佳答案

在日志中:

CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

意味着你需要runOnUiThread()用于更新以从 Thread 访问 Ui 元素:

   MainActivity.this.runOnUiThread(new Runnable() {

        @Override
        public void run() {
            // update textview here

        }
    });

将您的 setDots() 方法更改为:

public void setDots() {
        int counter = 0, numPoints =0;
                MainActivity.this.runOnUiThread(new Runnable() {
                   @Override
                   public void run() {
                    numPoints = numPoint.getProgress();
                 }
               });
          while(true) {
            if(counter++ < 10) {
                MainActivity.this.runOnUiThread(new Runnable() {
                   @Override
                   public void run() {
                     startButton.setText(startButton.getText() + ".  ");
                 }
               });
            }

            else {
                counter = 0;
            }

            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }           
    }

关于Android - 线程正在破坏应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14405127/

相关文章:

html - 使用 Android Intent 发送 HTML 邮件

android - 如何测试 Google App Invites

Android:定期执行代码

python - 使用多处理python将元素添加到列表

android - android 一起使用 scrollview 和 adjustPan

java - 根据另一个字符串数组的值从一个数组中仅提取某些对象

android - 如何从服务获取位置

c++ - 计算并发读取流中不同元素的数量

c# - 如果我有条件地 Monitor.Enter,而另一个线程位于临界区且没有锁,会发生什么情况?

java - 如何使用不同的 JUnit Runner 运行 Spring 单元测试?