在开始Android开发(以及一般的初学者开发)时我学到的第一件事就是UI不应该(并且在许多情况下不能)由主UI线程之外的任何其他线程更新。
我有一个AsyncTask,它在doInBackground()中移动了一堆文件。我有一个进度条,代表用户。
对于它(主要是由于懒惰)我决定在doInBackground()方法/线程中尝试progressBar.setProgress([更新进度]),令我惊讶的是,它工作正常。
然而,这似乎违背了我所学习的惯例。我知道AsyncTask有一个onProgressUpdate()或其他什么,但它让我有点困惑,我不确定它是否值得切换,因为当前的实现似乎工作正常。
我是否应该在此后台线程中更新进度条?
答案 0 :(得分:3)
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 线程,则会向{0}发布Runnable
,以避免CalledFromWrongThreadException
。
但是,总是使用UI线程进行与UI相关的调用; Android开发人员可以随时更改实现,而视图通常不是线程安全的。
答案 1 :(得分:1)
您不应该直接从ProgressBar
内部修改doInBackground()
和/或调用其任何方法,因为Android UI工具包不是线程安全的。
相反,从publishProgress()
内部调用doInBackground()
,您将在onProgressUpdate()
中的UI线程上收到后续回调,您可以根据需要修改ProgressBar
。< / p>