user849998
user849998

Reputation:

Android AsyncTask onPostExecute method

EDIT: If I do not use the progress at all, just showing the dialog, then everything works without any problems. But if i add progress, then dialog doesn't close(method onPostExecute() is not fired).


onPostExecute method is not executed. Where do I have a mistake? (Same result on emulator and on the device) I am also not sure if I should use Override notation for these methods

This is the rough solution for now. It works every time, but is not the proper and not the nice one. What I am doing: * I start a child activity using tabgroupactivity * Then i navigate to another activity in the child activity, so it is a current child of a parent * There is a webview, where I display information about one comment.. whatever * There is a link in the content displayed by the webView * when i click it, i start downloading the PDF file.

When the file is downloaded:

    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();
        }
    }

My Dialog object is disapeared, so if I try to call Dialog after the While loop, i just don't get it. So what I did is that every time i get new buffer from website, i check if the dialog is still visible and if the current byte together with the amount of bytes read up to now are greater than the full size of the file, then I close the dialog in the while loop. I tried using fileSize == read(amount of bytes), but it did not work, maybe they are not precisely mach each other when the file is downloaded

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;
        }

Upvotes: 4

Views: 4712

Answers (4)

Nabil Gardon
Nabil Gardon

Reputation: 175

Funny how you can post 3 times the same answer because people does not search before they post... You are NOT allowed to access the UI thread from anywhere but the UI Thread... That means that your Dialog.dismiss and Dialog.cancel can't be executed since it is not Thread safe...

To fix your problem you have several ways. First way : do NOT use AsyncTask as you will have 5 tasks (at max) running at every time... I send you to the Android Doc of AsyncTask, and the guidelines to Processes and Threads attached for further info.

Second way : Move all of your UI Thread-related methods in the onPostExecute(). This is thread-safe, and the result of doInBackground() is automatically transmitted to it.

Third way : use on of the following

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

The Runnable will be executed inside the UI Thread. So again. Thread-safe.

I recommend the second solution if you really do not need your app to be thoroughly optimized. If it does, use tasks manually added to a manually created ThreadPoolExecutor (again, see the doc of ThreadPoolExecutor).

While searching through the doc I found This :

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.)

If not on UI Thread, do not use AsyncTask but Task instead, with a ThreadPoolExecutor to wrap them.

This is why you should NOT use Asynctask : How can I make asynchronous URL connections on Android? look for my name in the answers.

Upvotes: 1

Chad Schultz
Chad Schultz

Reputation: 7860

I found this thread searching for the same problem. After much trial and error, I found two issues:

  1. I was sometimes canceling my Task in doInBackground instead of letting the method complete normally, causing onCancelled() to fire instead of onPostExecute(). Thanks for the tip, Kasper!

  2. I was apparently using the wrong method signature for onPostExecute. If you do not have a return type, it needs to be:

    protected void onPostExecute(Void v)

Not very intuitive, and not shown in the API, but once I did this that did the trick.

Upvotes: 0

kaspermoerch
kaspermoerch

Reputation: 16570

Is the parent of the AsyncTask cancelled/paused/destroyed before the AsyncTask finishes?

If yes, the AsyncTask might recieve a cancel() which results in onPostExecute() never to be run. To verify this, try overriding onCancelled()-method and check if it is run.

Upvotes: 2

teoREtik
teoREtik

Reputation: 7916

IMHO, you just need to remove super call.

Upvotes: -1

Related Questions