Android UI操作并不是线程安全的, UI操作必须在UI线程中执行,也就是说你不能在自己另起的一个thread里进行UI操作。
举个例子,下列代码是希望在自定义的thread中修改Activity里的button name。
ThreadHandlerDemoActivity.java
public class ThreadHandlerDemoActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
((Button) findViewById(R.id.button1))
.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
new MyThread(ThreadHandlerDemoActivity.this).start();
}
});
}
public void changeButtonText(){
((Button) findViewById(R.id.button1)).setText("aaa");
}
}
MyThread.java
public class MyThread extends Thread {
ThreadHandlerDemoActivity mainActivity;
public MyThread(ThreadHandlerDemoActivity mainActivity) {
this.mainActivity = mainActivity;
}
public void run() {
mainActivity.changeButtonText();
}
}
当你执行上面程序时,会抛出下列exception
$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
这是因为你在非UI线程里试图进行UI操作。
有时你还可能在非UI线程里试图进行UI操作时抛出下列exception
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
其中一个解决方法就是使用Handler。见下列代码
ThreadHandlerDemoActivity.java
Handler handler = new Handler() {
public void handleMessage (Message msg) {
changeButtonText();
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
((Button) findViewById(R.id.button1))
.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
new MyThread(handler).start();
}
});
}
public void changeButtonText(){
((Button) findViewById(R.id.button1)).setText("aaa");
}
}
MyThread.java
Handler handler;
public MyThread (Handler handler) {
this.handler = handler;
}
public void run() {
Message msg = new Message();
msg.what = 1;
handler.sendMessage(msg);
}
}
通过handler来进行UI操作则不会抛出exception.