我是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;
}
}
我在模拟器中运行后,它说:“不幸的是,应用名称已停止。” logcat的:
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新手。我不知道它可能是什么。
答案 0 :(得分: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
来电
答案 1 :(得分: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线程,即计时器。
答案 2 :(得分:1)
异常只有创建视图层次结构的原始线程才能触及其视图。
你不能这样做。
label.setText(String.valueOf("Time left: "));
这样做。
runOnUiThread(new Runnable() {
public void run() {
//Update UI Here
}
});
OR Handler执行此操作。
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
//.....
}
}
};
}