和许多其他的GUI 库一样,Android 的UI 也是线程不安全的。也就是说,如果想要更新应用程序里的UI 元素,则必须在主线程中进行,否则就会出现异常。了解AsyncTask的用法,请参见我的博客:(android高级---->Asynctask的源码分析)今天我们就来学习一下有关UI更新的一些知识。
目录:
今天我们通过一个小案例,来说明更新UI的全部测试内容:项目结构如下
在子线程中更新UI
一、 在MainActivity.java的onCreate方法中做一些初始化工作,初始化textView
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textView);
}
二、 点击threadUpdateUI按钮,触发在子线程中更新UI的事件
// 在子线程中更新UI
public void threadUpdateUI(View view) {
new Thread(new Runnable() {
@Override
public void run() {
textView.setText("I love you.");
}
}).start();
}
三、 运行结果如下,说明在子线程中的确不能更新UI
日志打印结果: Only the original thread that created a view hierarchy can touch its views.
测试真机崩溃:
用Handler机制实现UI的更新
一、 定义一个Handler,用于接收处理消息
public static final int UPDATE_TEXT = 1;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDATE_TEXT:
textView.setText("I Love you.");
break;
default:
break;
}
}
}
二、 点击按钮,触发在子线程中发送消息的事件
// 用handler处理上述问题
public void handlerUpdate(View view) {
new Thread(new Runnable() {
@Override
public void run() {
Message message = new Message();
message.what = UPDATE_TEXT;
handler.sendMessage(message); // 将Message对象发送出去
}
}).start();
}
结果正常,textView显示为:I love you
用AsyncTask机制实现UI的更新
一、 创建一个继承AsyncTask的内部类,命名为:MyAsynTask
private class MyAsynTask extends AsyncTask {
@Override
protected Void doInBackground(Void... params) {
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
textView.setText("I love you");
}
}
二、 点击按钮,创建AsyncTask的实例,并调用execute方法:
// 用AsyncTask处理上述问题
public void asynTask(View view) {
MyAsynTask myAsynTask = new MyAsynTask();
myAsynTask.execute();
}
结果正常,textView显示为:I love you。
友情链接
关于AsyncTask类的详细使用,请参见我的博客 (android高级---->Asynctask的源码分析)