web-dev-qa-db-fra.com

Android: comment attendre AsyncTask pour finir en Main Thread?

Je sais que la première chose que vous allez faire, c'est ... pourquoi diable, vous utilisez ensuite AsyncTask. 

Donc, voici mon problème, je travaille sur une application Android (API 7 pour Android 2.1 ou supérieure), et je teste sur l'émulateur et tout allait bien, alors j'ai testé sur HTC Sensation et il est dit NetworkOnMainThreadExeption! 

Je téléchargeais quelques images puis dessinais sur la carte.

Donc, pour résoudre ce problème tous les (connexion Internet) dans ce cas, le téléchargement des images, je dois mettre sur AsyncTask au travail.

J'ai donc besoin d'une méthode pour savoir quand toutes les images sont terminées pour pouvoir commencer à dessiner. 

J'essayais tellement et aucun résultat je n'ai aucune idée. J'ai une solution avec handler mais si je travaille sur un net plus lent, j'obtiens nullpointer (car les images ne sont pas téléchargées).

Alors aidez-moi s'il vous plaît. 

MODIFIER:

voici l'idée:

Bitmap bubbleIcon ;
    onCreate(){
     ...
// i am making call for Async
new ImgDown().execute(url);
//and then i calling functions and classes to draw with that picture bubbleIcon !
DrawOnMap(bubbleIcon);
}




//THIS IS ASYNC AND FOR EX. SUPPOSE I NEED TO DOWNLOAD THE PIC FIRST
     class ImgDown extends AsyncTask<String, Void, Bitmap> {

        private String url;

        public ImgDown() {
        }

        @Override
        protected Bitmap doInBackground(String... params) {
            url = params[0];
            try {
                return getBitmapFromURL(url);
            } catch (Exception err) {
            }

            return null;

        }

        @Override
        protected void onPostExecute(Bitmap result) {
            bubbleIcon = result;
            bubbleIcon = Bitmap
                    .createScaledBitmap(bubbleIcon, 70, 70, true);

        }

        public Bitmap getBitmapFromURL(String src) {
            try {
                Log.e("src", src);
                URL url = new URL(src);
                HttpURLConnection connection = (HttpURLConnection) url
                        .openConnection();
                connection.setDoInput(true);
                connection.connect();
                InputStream input = connection.getInputStream();
                // /tuka decode na slika vo pomalecuk kvalitet!
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inSampleSize = 3;
                Bitmap myBitmap = BitmapFactory
                        .decodeStream(new FlushedInputStream(input));
                Log.e("Bitmap", "returned");
                return myBitmap;
            } catch (IOException e) {
                e.printStackTrace();
                Log.e("getBitmapFromURL", e.getMessage());
                return null;
            }
        }

        class FlushedInputStream extends FilterInputStream {
            public FlushedInputStream(InputStream inputStream) {
                super(inputStream);
            }

            public long skip(long n) throws IOException {
                long totalBytesSkipped = 0L;
                while (totalBytesSkipped < n) {
                    long bytesSkipped = in.skip(n - totalBytesSkipped);
                    if (bytesSkipped == 0L) {
                        int byteValue = read();
                        if (byteValue < 0) {
                            break; // we reached EOF
                        } else {
                            bytesSkipped = 1; // we read one byte
                        }
                    }
                    totalBytesSkipped += bytesSkipped;
                }
                return totalBytesSkipped;
            }
        }
    }

j'espère que c'est plus clair maintenant.

10
user1730007
class OpenWorkTask extends AsyncTask {

    @Override
    protected Boolean doInBackground(String... params) {
        // do something
        return true;
    }

    @Override
    protected void onPostExecute(Boolean result) {
        // The results of the above method
        // Processing the results here
        myHandler.sendEmptyMessage(0);
    }

}

Handler myHandler = new Handler() {

    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
        case 0:
            // calling to this function from other pleaces
            // The notice call method of doing things
            break;
        default:
            break;
        }
    }
};
32
RookieWen

Vous pouvez écrire votre propre délégué pour déléguer des informations sur la fin de la tâche, en utilisant les principes OOP:

task_delegate.Java

public interface TaskDelegate {
    void TaskCompletionResult(String result);
}

main_activity.Java

public class MainActivity extends Activity implements TaskDelegate {

    //call this method when you need     
    private void startAsynctask() {
      myAsyncTask = new MyAsyncTask(this);
      myAsyncTask.execute();
     }

//your code

    @Override
    public void TaskCompletionResult(String result) {
        GetSomethingByResult(result);
    }
}

my_asynctask.Java

public class MyAsyncTask extends AsyncTask<Void, Integer, String> {

    private TaskDelegate delegate;

    protected MyAsyncTask(TaskDelegate delegate) {
        this.delegate = delegate;
    }

    //your code 

    @Override
    protected void onPostExecute(String result) {

        delegate.TaskCompletionResult(result);
    }
}
7
Yuliia Ashomok
class openWorkTask extends AsyncTask<String, String, Boolean> {

    @Override
    protected Boolean doInBackground(String... params) {
        //do something
        return true;
    }

    @Override
    protected void onPostExecute(Boolean result) {
        // The results of the above method
        // Processing the results here
    }
}
2
RookieWen

J'utiliserais un dialogue de progression si j'étais vous. De cette façon, les utilisateurs peuvent voir qu'il se passe quelque chose pendant le téléchargement de l'image par ASyncTask. Sur PostExecute, appelez une méthode de votre code principal qui vérifie si les images sont nulles. N'oubliez pas que vous ne pouvez pas mettre à jour l'interface utilisateur dans la méthode doInBackground. Par conséquent, aucune interface utilisateur ne fonctionne dans onPreExecute ou onPostExecute. 

private class DownloadPictures extends AsyncTask<String, Void, String> 
{

    ProgressDialog progressDialog;

    @Override
    protected String doInBackground(String... params) 
    {

        //Download your pictures

        return null;

    }

    @Override
    protected void onPostExecute(String result) 
    {

        progressDialog.cancel();

        //Call your method that checks if the pictures were downloaded

    }

    @Override
    protected void onPreExecute() {

        progressDialog = new ProgressDialog(
                YourActivity.this);
        progressDialog.setMessage("Downloading...");
        progressDialog.setCancelable(false);
        progressDialog.show();

    }

    @Override
    protected void onProgressUpdate(Void... values) {
        // Do nothing
    }

}
0
John P.