-1

我是 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 新手。我不知道它可能是什么。

4

3 回答 3

4

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

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

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

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

            }
        }, delay, period);
}

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

于 2013-03-26T15:17:21.163 回答
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 线程。

于 2013-03-26T15:20:08.343 回答
1

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

你不能这样做。

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-26T15:17:29.490 回答