无意间在子线程中对ProgressBar 进行了更新,发现应用能正常运行。
我们都知道控件只能在UI线程中进行更新,于是到网上搜啊搜啊,找不到答案,只能到源码中找。
一下是在源码中找到的一些代码,个人感觉应该是这个原理,有错误,请高手改正。
无论是调用ProgressBar的.incrementProgressBy(len)还是setProgress(len)
都是要调用下面这个方法:
private synchronized void refreshProgress(int id, int progress, boolean fromUser) {
if (mUiThreadId == Thread.currentThread().getId()){//是否是UI线程,是的话直接更新
doRefreshProgress(id, progress, fromUser);
} else {//不是调用下面的post(r),r = new RefreshProgressRunnable
RefreshProgressRunnable r;
if (mRefreshProgressRunnable != null) {
// Use cached RefreshProgressRunnable if available
r = mRefreshProgressRunnable;
// Uncache it
mRefreshProgressRunnable = null;
r.setup(id, progress, fromUser);
} else {
// Make a new one
r = new RefreshProgressRunnable(id, progress, fromUser);
}
post(r);
}
}
private class RefreshProgressRunnable implements Runnable {
public void run() {//核心回调的代码
doRefreshProgress(mId, mProgress, mFromUser, true);
// Put ourselves back in the cache when we are done
mRefreshProgressRunnable = this;
}
}
post(r)----->执行到View的
public boolean post(Runnable action) {
Handler handler;
if (mAttachInfo != null) {
handler = mAttachInfo.mHandler;
} else {
// Assume that post will succeed later
ViewRoot.getRunQueue().post(action);
return true;
}
return handler.post(action);
}
AttachInfo是View的一个内部类
void dispatchAttachedToWindow(AttachInfo info, int visibility) {
//System.out.println("Attached! " + this);
mAttachInfo = info;
}
}//这个方法应该是由系统的UI来调用,由系统传入info,处于UI线程。
上面post方法中handler.post(action);就可以更新UI了。
ProgressDialog也能在子线程中更新:
public void incrementProgressBy(int diff) {
if (mProgress != null) {
mProgress.incrementProgressBy(diff);
onProgressChanged();
} else {
mIncrementBy += diff;
}
}
这个mProgress生命在ProgressDialog的53行
private ProgressBar mProgress;
也就是说,ProgressDialog更新UI调用的是ProgressBar来进行更新。
本文探讨了在Android中从子线程更新ProgressBar和ProgressDialog的实现机制。通过分析源码,揭示了即使不在UI线程中,也能正确更新UI组件的原因。
3222

被折叠的 条评论
为什么被折叠?



