从Handler调用的AsyncTask不会执行doInBackground [英] AsyncTask called from Handler will not execute doInBackground
问题描述
我正在开发的应用程序使用后台线程通过 API 下载图像列表,然后在幻灯片中显示图像.
The application I'm working on is using a background thread to download a list of images through a API, then display the images in a slideshow.
有一个后台任务(当前为 AsyncTask)来定期获取新图像.
There is a background task (currently AsyncTask) to periodically fetch the new images.
我没有收到关于错误线程等的任何错误消息,只是 AsyncTasks 的第二个实例不会运行 doInBackground 方法.
I'm not getting any error messages about the wrong Thread etc, it's just that the AsyncTasks's second instance will not run the doInBackground method.
这是活动中的一些代码:
Here is some code from the Activity:
private DownloadTask mDownloadTask = null;
private Handler mHandler;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if(mDownloadTask != null) {
mDownloadTask.cancel(true);
}
mDownloadTask = new DownloadTask();
mDownloadTask.execute((Void[]) null);
}
};
mDownloadTask = new DownloadTask();
mDownloadTask.execute((Void[]) null);
}
DownloadTask
看起来像这样:
@Override
protected List<String> doInBackground(Void... voids) {
// Download list of URLs from server, etc.
}
@Override
protected void onPostExecute(List<String> urls) {
mHandler.sendEmptyMessageDelayed(111, 5000);
}
将调用处理程序,将调用 onPreExecute(在 AsyncTask 中)并且 DownloadTask 的初始运行(就在 onCreate
中)也有效.
The handler will be called, the onPreExecute (in the AsyncTask) will be called and the initial run of DownloadTask (right in onCreate
) also works.
根据这个问题:Android SDK AsyncTask doInBackground not running (subclass) ,可能与 SDK15 相关.
According to this question: Android SDK AsyncTask doInBackground not running (subclass) , it might be SDK15 related.
感谢您的提示.
更新 因为我收到评论说 Handler 可能不在 UI 线程中(这很奇怪,因为 Thread.currentThread
在 onCreate 和 Handlers 中是相同的handleMessage
方法,我修改了 handleMessage
方法为:
Update As I received comments that the Handler might not be in the UI thread (which is weird, as Thread.currentThread
is the same both in onCreate and the Handlers handleMessage
method, I revised the handleMessage
method to:
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
runOnUiThread(new Runnable() {
@Override
public void run() {
if(mDownloadTask != null) {
mDownloadTask.cancel(true);
}
mDownloadTask = new DownloadTask();
mDownloadTask.execute((Void[]) null);
}
});
}
};
仍然没有成功.
更新完整的 DownloadTask 类
Update the full DownloadTask class
class DownloadTask extends AsyncTask<Void, Void, List<String>> {
@Override
protected void onPreExecute() {
// Cancel the animation.
if (mSlideshowAnimation != null) {
mSlideshowAnimation.cancel(true);
}
mImageView1.setVisibility(View.GONE);
mImageView2.setVisibility(View.GONE);
animate(mProgressBar).alpha(1.0f).setDuration(500).start();
Log.d(TAG, "Download preparation done.");
}
@Override
protected List<String> doInBackground(Void... voids) {
Log.d(TAG, "Download");
SharedPreferences s = getSharedPreferences("access", Context.MODE_PRIVATE);
String token = s.getString("token", null);
Log.d(TAG, "Downloading slideshows.");
List<String> urls = new ArrayList<String>();
Slideshow[] slideshows = new Api(SlideshowActivity.this).getSlideshows(token);
for (Slideshow slideshow : slideshows) {
urls.addAll(slideshow.getAllPhotoUrls());
}
Log.d(TAG, "Downloading slideshows: " + slideshows.length);
for (String url : urls) {
try {
url = Api.HOST + url;
if (!Cache.fileExists(Cache.getCacheFilenameForUrl(SlideshowActivity.this, url))) {
Cache.cacheStream(SlideshowActivity.this, HttpHelper.download(SlideshowActivity.this, url), url);
} else {
Log.d(TAG, "Cached: " + url);
}
} catch (IOException e) {
Log.e(TAG, "Error while downloading.", e);
}
}
Log.d(TAG, "Downloading slideshows finished.");
return urls;
}
@Override
protected void onPostExecute(List<String> urls) {
Log.d(TAG, "download successful");
animate(mProgressBar).alpha(0.0f).setDuration(500).start();
mCurrentImageIndex = -1;
mImageUrls = urls;
mSlideshowAnimation = new SlideshowAnimation();
mSlideshowAnimation.execute((Void[]) null);
mHandler.sendEmptyMessageDelayed(111, 5000);
}
}
推荐答案
感谢与 Waqas 的有益讨论(谢谢!)我终于发现了代码中的错误.事实上,上面写的所有内容都是正确的,并且可以正常工作.我的问题是第二个任务阻止了第一个任务,反之亦然.
Thanks to a helpful discussion with Waqas (thank you!) I finally uncovered the error in my code. In fact all above written is correct and works as is. Issue with my case was that the second task blocked the first one and vice versa.
在 Google 网上论坛上找到这篇文章可能是一个巧合:http://groups.google.com/group/android-developers/browse_thread/thread/f0cd114c57ceefe3?tvc=2&q=AsyncTask+in+Android+4.0 .建议所有参与线程的人仔细阅读此讨论.
It was perhaps a coincidence to find this post on Google Groups: http://groups.google.com/group/android-developers/browse_thread/thread/f0cd114c57ceefe3?tvc=2&q=AsyncTask+in+Android+4.0 . Recommend that everyone involved in threading reads this discussion carefully.
AsyncTask 将线程模型切换为串行执行器(再次),这似乎与我拥有 2 个 AsyncTask 的方法不兼容.
AsyncTask switched the Threading model to a serial executor (again), which is not compatible with my approach of having 2 AsyncTasks it seems.
最后,我将下载"的处理切换为经典的 Thread
并使用 Handler
发布消息以在必要时取消幻灯片.使用处理程序 sendEmptyMessageDelayed
我将在一段时间后简单地重新创建下载线程以刷新数据.
Finally I switched the handling of the "Download" to a classic Thread
and used the Handler
to post messages to cancel the Slideshow if neccessary. Using the Handlers sendEmptyMessageDelayed
I will simple recreate the Download Thread after a while to refresh the data.
感谢所有评论 &答案.
Thanks to all comments & answers.
这篇关于从Handler调用的AsyncTask不会执行doInBackground的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!