从Handler调用的AsyncTask不会执行doInBackground [英] AsyncTask called from Handler will not execute doInBackground

查看:18
本文介绍了从Handler调用的AsyncTask不会执行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&a​​mp;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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆