Ant*_*ony 5 user-interface android thread-safety android-asynctask
我有一个AsyncTask更新ActionBarSherlock进度实现.不知怎的,onProgressUpdate虽然声称在UI线程上执行,却引发了一个线程错误.
protected void onProgressUpdate(Integer... values)
{
setSupportProgress(values[0]);
}
Run Code Online (Sandbox Code Playgroud)
错误是:
03-06 00:13:11.672:E/AndroidRuntime(4183):at com.anthonymandra.framework.GalleryActivity $ ShareTask.onProgressUpdate(GalleryActivity.java:476)
只有创建视图层次结构的原始线程才能触及其视图.
据我所知,我应该访问UI线程...
我在我的应用程序中有很多工作AsyncTasks,但是根据要求这里是doInBackground(简化):
for (MediaObject image : toShare)
{
BufferedInputStream imageData = image.getThumbStream();
File swapFile = getSwapFile(...);
write(swapFile, imageData);
++completed;
float progress = (float) completed / toShare.size();
int progressLocation = (int) Math.ceil(progressRange * progress);
onProgressUpdate(progressLocation);
}
Run Code Online (Sandbox Code Playgroud)
好吧,问题是当你应该调用publishProgress 时,你却调用了onProgressUpdate。OP自己解决了这个问题,所以我只是复制粘贴它,这样他/她就不需要等待接受答案。下面是 AsyncTasks 如何工作的信息,这是很好的知识。
您是AsyncTask在 UI 线程上创建的吗?如果你不是,那就是问题所在。onProgressUpdate将在创建AsyncTask.
更新:让我们有一些代码挖掘时间(API 15 源代码)!
protected final void publishProgress(Progress... values) {
if (!isCancelled()) {
sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
new AsyncTaskResult<Progress>(this, values)).sendToTarget();
}
}
Run Code Online (Sandbox Code Playgroud)
这个家伙将其称为静态HandlersHandler。文档说:
当您创建一个新的处理程序时,它会绑定到创建它的线程的线程/消息队列 - 从那时起,它将向该消息队列传递消息和可运行对象,并在它们从消息中出来时执行它们队列。
感谢 Bruno Mateus 的文档查找技巧:
看,我在文档页面找到:线程规则 - 为了使此类正常工作,必须遵循一些线程规则: - AsyncTask 类必须加载到 UI 线程上。从 JELLY_BEAN 开始,这是自动完成的。- 任务实例必须在UI线程上创建。必须在 UI 线程上调用execute(Params...)。- 不要手动调用 onPreExecute()、onPostExecute(Result)、doInBackground(Params...)、onProgressUpdate(Progress...)。- 该任务只能执行一次(如果尝试第二次执行,将抛出异常。)