【问题标题】:Unfortunately, app name has stopped [duplicate]不幸的是,应用名称已停止[重复]
【发布时间】:2013-03-26 23:33:55
【问题描述】:

我是 Java 新手,我正在尝试使用带有插件的 eclipse 为 Android 编写一个简单的应用程序。 代码如下:

package com.example.pushthebutton;

import java.util.Timer;
import java.util.TimerTask;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.widget.TextView;

public class MainActivity extends Activity {
    int counter = 30;
    TextView label;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        int delay = 0; 
        int period = 1000;
        Timer timer = new Timer();
        label = (TextView) findViewById(R.id.textView1);
        timer.scheduleAtFixedRate(new TimerTask() {
                public void run() {
                    label.setText(String.valueOf("Time left: "));
                    counter--;
                }
            }, delay, period);
    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}

我在模拟器中运行它后,它说:“不幸的是,应用程序名称已停止。” 日志猫:

03-26 15:05:47.499: E/AndroidRuntime(1269): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
03-26 15:05:47.499: E/AndroidRuntime(1269):     at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:4746)
03-26 15:05:47.499: E/AndroidRuntime(1269):     at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:823)
03-26 15:05:47.499: E/AndroidRuntime(1269):     at android.view.View.requestLayout(View.java:15473)
03-26 15:05:47.499: E/AndroidRuntime(1269):     at android.view.View.requestLayout(View.java:15473)
03-26 15:05:47.499: E/AndroidRuntime(1269):     at android.view.View.requestLayout(View.java:15473)
03-26 15:05:47.499: E/AndroidRuntime(1269):     at android.view.View.requestLayout(View.java:15473)
03-26 15:05:47.499: E/AndroidRuntime(1269):     at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:318)
03-26 15:05:47.499: E/AndroidRuntime(1269):     at android.view.View.requestLayout(View.java:15473)
03-26 15:05:47.499: E/AndroidRuntime(1269):     at android.widget.TextView.checkForRelayout(TextView.java:6452)
03-26 15:05:47.499: E/AndroidRuntime(1269):     at android.widget.TextView.setText(TextView.java:3696)
03-26 15:05:47.499: E/AndroidRuntime(1269):     at android.widget.TextView.setText(TextView.java:3554)
03-26 15:05:47.499: E/AndroidRuntime(1269):     at android.widget.TextView.setText(TextView.java:3529)
03-26 15:05:47.499: E/AndroidRuntime(1269):     at com.example.pushthebutton.MainActivity$1.run(MainActivity.java:24)
03-26 15:05:47.499: E/AndroidRuntime(1269):     at java.util.Timer$TimerImpl.run(Timer.java:284)
03-26 15:05:47.659: E/StrictMode(628): null

我是 Java 新手。我不知道它会是什么。

【问题讨论】:

  • 你不需要使用String.valueOf("Time left: ")"Time left: " 已经是一个字符串。
  • @unholysampler 是的,那时我还不知道 runOnUiThread,所以我想我应该投它什么的。

标签: java android


【解决方案1】:

您不能从不同于 UI 线程的线程更新每个视图:

以这种方式更改您的代码:

timer.scheduleAtFixedRate(new TimerTask() {
            public void run() {

                runOnUiThread(new Runnable()
                    public void run() {
                        label.setText(String.valueOf("Time left: "));
                        counter--;
                        }
                  ));

            }
        }, delay, period);
}

通过这种方式,您要求 Android 在 UI Thread 上执行 setText 调用

【讨论】:

    【解决方案2】:

    试试这个:

     timer.scheduleAtFixedRate(new TimerTask() {
                public void run() {
                    runOnUiThread(new Runnable() {
                    @Override
            public void run() {
            label.setText(String.valueOf("Time left: "));
                        counter--;
            }
                }
              }
            }, delay, period);
    

    您正在从非 UI 线程修改 UI 线程,即计时器。

    【讨论】:

      【解决方案3】:

      异常 只有创建视图层次结构的原始线程才能接触其视图。

      你不能这样做。

      label.setText(String.valueOf("Time left: "));
      

      这样做。

      runOnUiThread(new Runnable() {
         public void run() {
            //Update UI Here
         }
      });
      

      或处理程序来执行此操作。

      示例

      void startHeavyDutyStuff() {
      
        // Here is the heavy-duty thread
        Thread t = new Thread() {
      
            public void run() {
                while (true) {
      
                    mResults = doSomethingExpensive();
      
                    //Send update to the main thread
                    messageHandler.sendMessage(Message.obtain(messageHandler, mResults)); 
                }
      
            }
        };
        t.start();
      }
      
      // Instantiating the Handler associated with the main thread.
      private Handler messageHandler = new Handler() {
      
            @Override
            public void handleMessage(Message msg) {  
                switch(msg.what) {
                    //handle update
                    //.....
                }
            }
      
        };
      }
      

      【讨论】:

      • 谢谢 :) 能给我举个例子吗?
      • 像魅力一样工作:)。接受:) 谢谢!
      猜你喜欢
      • 2013-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-18
      • 2014-10-30
      • 1970-01-01
      • 2014-07-25
      相关资源
      最近更新 更多