我在开始android开发(以及一般的初学者开发)时学到的第一件事是,除了主ui线程之外,ui不应该(在很多情况下也不能)被任何其他线程更新。
我有一个异步任务,它正在移动doinbackground()中的一堆文件。我有一个progressbar,它向用户表示这一点。
我决定尝试doinbackground()方法/线程中的progressbar.setprogress([updated progress]),出乎意料的是,它工作得很好。
然而,这似乎违背了我学到的惯例。我知道asynctask有一个onprogressupdate()或其他什么东西,但它让我有点困惑,我不确定它是否值得切换,因为当前的实现似乎工作正常。
我不应该更新这个后台线程中的progressbar吗?
最佳答案
ProgressBar
能够在不崩溃的情况下执行此操作,因为setProgress()
调用refreshProgress()
(线程安全的方法),此时是真正刷新视图的时候。
private synchronized void refreshProgress(int id, int progress, boolean fromUser) {
if (mUiThreadId == Thread.currentThread().getId()) {
doRefreshProgress(id, progress, fromUser, true);
} else {
if (mRefreshProgressRunnable == null) {
mRefreshProgressRunnable = new RefreshProgressRunnable();
}
final RefreshData rd = RefreshData.obtain(id, progress, fromUser);
mRefreshData.add(rd);
if (mAttached && !mRefreshIsPosted) {
post(mRefreshProgressRunnable);
mRefreshIsPosted = true;
}
}
}
如果方法调用是非ui线程,它会向ui线程发送一个
Runnable
,从而避免CalledFromWrongThreadException
s。但是,始终使用ui线程进行ui相关的调用;android开发人员可以随时更改实现,并且视图通常不是线程安全的。