Android AsyncTask метод onPostExecute - PullRequest
4 голосов
/ 29 сентября 2011

РЕДАКТИРОВАТЬ: Если я вообще не использую прогресс, просто показываю диалог, то все работает без проблем.Но если я добавляю прогресс, то диалоговое окно не закрывается (метод onPostExecute () не запускается).


Метод onPostExecute не выполняется.Где у меня ошибка?(Тот же результат на эмуляторе и на устройстве) Я также не уверен, должен ли я использовать нотацию Override для этих методов

Это грубое решение на данный момент.Это работает каждый раз, но не является правильным и не хорошим.Что я делаю: * Я запускаю дочернее действие с помощью tabgroupactivity * Затем я перехожу к другому действию в дочернем действии, так что это текущий дочерний элемент родителя * Есть веб-просмотр, где я отображаю информацию об одном комментарии ... что угодно* В содержимом, отображаемом webView *, есть ссылка *, когда я щелкаю по нему, я начинаю скачивать файл PDF.

Когда файл загружается:

    while ((current = bis.read()) != -1) {
        read = read + current;
        baf.append((byte) current);
        Dialog.setProgress(read);

        if(Dialog.isShowing() && read+2*current>file_size){
            Dialog.dismiss();
            Dialog.cancel();
        }
    }

Мой объект диалогаисчез, поэтому, если я попытаюсь вызвать Dialog после цикла While, я просто не получу его.Итак, что я сделал, так это то, что каждый раз, когда я получаю новый буфер с веб-сайта, я проверяю, отображается ли диалоговое окно, и если текущий байт вместе с количеством прочитанных до сих пор байтов больше, чем полный размер файла, то язакройте диалог в цикле while.Я пытался использовать fileSize == read (количество байтов), но это не сработало, возможно, они не точно совпадают друг с другом при загрузке файла

private class DownloadPDFFile extends AsyncTask<String, Integer, Void> {
    private ProgressDialog Dialog = new ProgressDialog(getParent());

    protected void onPreExecute() {
        Dialog.setMessage("Downloading PDF file..");
        Dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        Dialog.setCancelable(false);
        // Dialog.setMax(1000);
        Dialog.setProgress(0);
        Dialog.show();
    }

    protected Void doInBackground(String... urls) {
        File file=null;
        int file_size = 0;
        try {
            URL url = new URL(urls[0]);
            URLConnection urlConnection = url.openConnection();
            urlConnection.connect();
            file_size = urlConnection.getContentLength();
            Dialog.setMax(file_size);
        } catch (IOException e) {

        }

        try {
            URL url1 = new URL(urls[0]); // you can // link

            file = new File("skm_intern_pdf.pdf");

            URLConnection ucon = url1.openConnection();

            InputStream is = ucon.getInputStream();

            BufferedInputStream bis = new BufferedInputStream(is);

            ByteArrayBuffer baf = new ByteArrayBuffer(5000);
            int read = 0;
            int current = 0;
            while ((current = bis.read()) != -1) {
                read = read + current;
                baf.append((byte) current);
                Dialog.setProgress(read);

                if(Dialog.isShowing() && read+2*current>file_size){
                    Dialog.dismiss();
                    Dialog.cancel();
                }
            }

            FileOutputStream fos = openFileOutput("skm_pdf.pdf",
                    Context.MODE_WORLD_WRITEABLE);
            fos.write(baf.toByteArray());
            fos.flush();
            fos.close();

        } catch (IOException e) {

        }

        return null;
        }

Ответы [ 4 ]

2 голосов
/ 29 сентября 2011

Отменен ли / приостановлен / уничтожен родительский элемент AsyncTask до завершения AsyncTask?

Если да, AsyncTask может получить cancel(), в результате чего onPostExecute() никогда не будет запущен. Чтобы убедиться в этом, попробуйте переопределить onCancelled() -метод и проверьте, запущен ли он.

1 голос
/ 29 октября 2011

Забавно, как вы можете публиковать 3 раза один и тот же ответ, потому что люди не ищут, прежде чем они отправят ... Вам НЕ разрешен доступ к потоку пользовательского интерфейса из любого места, кроме потока пользовательского интерфейса ... Это означает, что ваши Dialog.dismiss и Dialog.cancel не могут быть выполнены, поскольку он не является безопасным для потока ...

Чтобы решить вашу проблему, у вас есть несколько способов. Первый способ: НЕ используйте AsyncTask, так как у вас будет запущено 5 задач (не более) каждый раз ... Я отправляю вас в Android Doc AsyncTask, и инструкции для процессов и потоков прилагаются для получения дополнительной информации.

Второй способ: Переместить все методы, связанные с вашим пользовательским интерфейсом, в onPostExecute(). Это поточно-ориентированный, и результат doInBackground() автоматически передается на него.

Третий способ: использовать следующее

Activity.runOnUiThread(Runnable)
View.post(Runnable)
View.postDelayed(Runnable, long)

Runnable будет выполняться внутри потока пользовательского интерфейса. Итак, еще раз. Потокобезопасна.

Я рекомендую второе решение, если вам действительно не нужно, чтобы ваше приложение было тщательно оптимизировано. Если это так, используйте задачи, добавленные вручную к созданному вручную ThreadPoolExecutor (снова см. Документ ThreadPoolExecutor).

При поиске в документе я нашел это:

Для правильной работы этого класса необходимо соблюдать несколько правил потоков:

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, а вместо этого Задачу с ThreadPoolExecutor, чтобы обернуть их.

Вот почему НЕ следует использовать Asynctask: Как я могу устанавливать асинхронные URL-соединения на Android? поищите мое имя в ответах.

0 голосов
/ 20 января 2012

Я нашел эту тему в поисках той же проблемы. После долгих проб и ошибок я обнаружил две проблемы:

  1. Иногда я отменял свою задачу в doInBackground вместо того, чтобы позволить нормальному завершению метода, вызывая срабатывание onCancelled () вместо onPostExecute (). Спасибо за совет, Каспер!

  2. Я явно использовал неправильную сигнатуру метода для onPostExecute. Если у вас нет типа возврата, он должен быть:

    защищенный void onPostExecute (Void v)

Не очень интуитивно понятно и не показано в API, но как только я это сделал, это помогло.

0 голосов
/ 29 сентября 2011

ИМХО, вам просто нужно удалить супер вызов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...