Вопрос по android, android-asynctask – AsyncTask, вызываемый из Handler, не будет выполнять doInBackground

12

Приложение, над которым я работаю, использует фоновый поток для загрузки списка изображений через API, а затем отображает изображения в виде слайд-шоу.

Существует фоновая задача (в настоящее время AsyncTask) для периодической загрузки новых изображений.

Я не получаю никаких сообщений об ошибках о неправильном потоке и т. Д., Просто второй экземпляр AsyncTasks не будет запускать метод doInBackground.

Вот некоторый код из Activity:

<code>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);
}
</code>

DownloadTask выглядит так:

<code>@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);
}
</code>

Будет вызван обработчик, будет вызываться onPreExecute (в AsyncTask) и начальный запуск DownloadTask (прямо вonCreate) тоже работает.

По этому вопросу:Android SDK AsyncTask doInBackground не работает (подкласс) , это может быть связано с SDK15.

Спасибо за любые подсказки.

Update Как я получил комментарии, что обработчик может не быть в потоке пользовательского интерфейса (что странно, какThread.currentThread одинаково как в onCreate, так и в обработчикахhandleMessage метод, я пересмотрелhandleMessage метод для:

<code>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);
            }
        });
    }
};
</code>

Все еще без успеха.

Update полный класс DownloadTask

<code>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);
    }
}
</code>
Вы можете опубликовать свой полный класс DownloadTask? waqaslam
@Frankenstein - это то, что я делаю вmDownloadTask = new DownloadTask(); оба раза? Sebastian Roth
Один объект AsyncTask может быть выполнен только один раз. Поэтому попробуйте изменить свой код и вместо этого использовать объект класса AsyncTask, напрямую использовать его как новый DownloadTask (). Execute (); MKJParekh
Не пиши.execute((Void[]) null), Это можно написать.execute(). Hauleth
@Hauleth может быть, но создает предупреждения компилятора дляunchecked varargs параметр. Sebastian Roth

Ваш Ответ

2   ответа
3

Handler это вид потока в Android, и AsyncTask также работает в другом потоке. Когда вы используете AsyncTask, есть несколько правил ..

There are a few threading rules that must be followed for this class to work properly:

The task instance must be created on the UI thread. execute(Params...) must be invoked on the UI thread. Do not call onPreExecute(), onPostExecute(Result), doInBackground(Params...), onProgressUpdate(Progress...) manually. The task can be executed only once (an exception will be thrown if a second execution is attempted.)

Таким образом, в нем четко сказано, что AsyncTAsk должен вызываться из потока пользовательского интерфейса ... где, как вы называете его из обработчика, который не является потоком пользовательского интерфейса ...

хорошо попробуй это тоже

mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            if(mDownloadTask != null) {
                mDownloadTask.cancel(true);
            }
           if([isCancelled()][1]){
            mDownloadTask = new DownloadTask();
            mDownloadTask.execute((Void[]) null);
          } // i assume your task is not getting cancelled before starting it again..
        }
    });
  }
};

а также документация говорит об этом ..

There are two main uses for a Handler:

(1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceedednew Handler().post(new Runnable() { @Override public void run() { try { Thread.sleep(60000); } catch (InterruptedException e) { e.printStackTrace(); } } });Error: User Rate Limit ExceededonCreateError: User Rate Limit Exceeded
Error: User Rate Limit Exceedednew Handler()Error: User Rate Limit Exceeded
14

Благодаря полезной дискуссии с Вакасом (спасибо!) Я наконец-то обнаружил ошибку в своем коде. На самом деле все выше написанное верно и работает как есть. Проблема с моим делом заключалась в том, что второе задание заблокировало первое, и наоборот.

Возможно, это было совпадение, чтобы найти этот пост в группах Google:http://groups.google.com/group/android-developers/browse_thread/thread/f0cd114c57ceefe3?tvc=2&q=AsyncTask+in+Android+4.0 , Рекомендую всем, кто участвует в работе с потоками, внимательно прочитать это обсуждение.

AsyncTask переключил модель Threading на последовательного исполнителя (опять же), что, по-моему, несовместимо с моим подходом к использованию двух AsyncTasks.

Наконец, я переключил обработку & quot; Скачать & quot; к классикеThread и использовалHandler отправлять сообщения, чтобы отменить слайд-шоу, если это необходимо. Использование обработчиковsendEmptyMessageDelayed Через некоторое время я просто воссоздаю тему загрузки, чтобы обновить данные.

Спасибо всем комментариям & amp; ответы.

Похожие вопросы