更新AndroidUI线程的方法
2015-04-27 本文已影响527人
几千里也
参考
重点
- Do not block the UI thread
- Do not access the Android UI toolkit from outside the UI thread
这样写是不对的
findViewById(R.id.demo).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
Bitmap b = loadImageFromNetwork("http://www.baidu.com/img/bdlogo.png");
mImageView.setImageBitmap(b);
}
}).start();
}
});
do not access the Android UI toolkit from outside the UI thread—this sample modifies the ImageView from the worker thread instead of the UI thread. This can result in undefined and unexpected behavior, which can be difficult and time-consuming to track down.
可以改成这样的
Android offers several ways to access the UI thread from other threads. Here is a list of methods that can help:
- Activity.runOnUiThread(Runnable)
- View.post(Runnable)
- View.postDelayed(Runnable, long)
findViewById(R.id.demo).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
final Bitmap bitmap = loadImageFromNetwork(http://www.baidu.com/img/bdlogo.png);
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
mImageView.setImageBitmap(bitmap);
}
});
}
}).start();
}
});
我们看一下 runOnUiThread 的源码:
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}
会发现此方法首先判断当前线程是不是 UI线程,不是的话使用 Handler 的 post 方法,是的话直接调用 run 方法。
我们接着看 View.post(Runnable) 的写法:
findViewById(R.id.demo).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
final Bitmap bitmap = loadImageFromNetwork(http://www.baidu.com/img/bdlogo.png);
mImageView.post(new Runnable() {
@Override
public void run() {
mImageView.setImageBitmap(bitmap);
}
});
}
}).start();
}
});
通过查看 View.post(Runnable) 的源码:
public boolean post(Runnable action) {
final AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
return attachInfo.mHandler.post(action);
}
// Assume that post will succeed later
ViewRootImpl.getRunQueue().post(action);
return true;
}
能够发现它其实也调用了 Handler 的 post 方法。View.postDelayed(Runnable, long) 就比 View.post(Runnable) 多了个时间参数,很好理解,不做赘述。
综上可知,前面提到的三种方法其实都是对 Handle + Message 的包装。
用 AsyncTask 更新 UI
Android 那帮人真是为开发者着想啊,AsyncTask 真是太好用了。同时,需要注意以下几点:
- AsyncTask 必须声明在 UI 线程上。
- AsyncTask 必须在 UI 线程上实例化。
- 必须通过 execute() 方法执行任务。
- 不可以直接调用 onPreExecute()、onPostExecute(Resut)、doInBackground(Params...)、onProgressUpdate(Progress...) 方法。