web-dev-qa-db-fra.com

Android - AsyncTask ne s'exécute pas

Je sais qu'il y a déjà beaucoup de questions avec ce titre mais je n'ai toujours pas trouvé de solution pour mon cas.

J'ai le code suivant qui obtient les données des utilisateurs d'une base de données en ligne. Le problème est, comme indiqué dans le titre, que le AsyncTask ne démarre pas.

Voici mon code:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getData(); // retrieves "friends" data from database
    FloatingActionButton btn3 = (FloatingActionButton) findViewById(R.id.button_add_new_friend);
    btn3.setBackgroundTintList(getResources().getColorStateList(R.color.Blonde));
    btn3.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            LayoutInflater layoutInflater = LayoutInflater.from(profile.this);
            View promptView = layoutInflater.inflate(R.layout.input_new_friend, null);
            AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(profile.this);
            alertDialogBuilder.setView(promptView);

            final EditText editText1 = (EditText) promptView.findViewById(R.id.edittext_addnewfriend);

            // setup a dialog window
            alertDialogBuilder.setCancelable(false)
                .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {

                        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
                        StrictMode.setThreadPolicy(policy);

                        InputStream is = null;

                        // add values to the database
                        String friend = "" + editText1.getText();

                        // Verify the user in the USERS database - get users data from the dabase
                        GetDataJSON g = new GetDataJSON();
                        g.execute();                                
                        if (friends.contains(friend)) // if you are already friends with that user
                            Toast.makeText(getApplicationContext(), "You are already friends with that user!",
                                Toast.LENGTH_LONG).show();
                        else {
                            if (!users.contains(friend)) // the user doesn't exist in our database
                                Toast.makeText(getApplicationContext(), "That user doesn't exist! You either haven't introduced the right email or he's not a registered user within Poinder.",
                                    Toast.LENGTH_LONG).show();
                        else // the user exists so we add him to the friends list
                        {
                            //do something
                        }
}

// Getting the users
protected void showList2(){
    try {
        JSONObject jsonObj = new JSONObject(myJSON);
        people = jsonObj.getJSONArray(TAG_RESULTS);

        for(int i=0;i<people.length();i++){
            JSONObject c = people.getJSONObject(i);
            String user = c.getString(TAG_USER);
            String email = c.getString(TAG_EMAIL);
            Double location_latitude = c.getDouble(TAG_LATITUDE);
            Double location_longitude = c.getDouble(TAG_LONGITUDE);

            users.add(email);
        }

    } catch (JSONException e) {
        e.printStackTrace();
    }

}

// Getting the users
private class GetDataJSON extends AsyncTask<Void, Void, String> {

    @Override
    protected String doInBackground(Void... params) {
        DefaultHttpClient httpclient = new DefaultHttpClient(new BasicHttpParams());
        HttpPost httppost = new HttpPost("http://xxxxxxx/friends_out.php");

        // Depends on your web service
        httppost.setHeader("Content-type", "application/json");

        InputStream inputStream = null;
        String result = null;
        try {
            HttpResponse response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();

            inputStream = entity.getContent();
            // json is UTF-8 by default
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"), 8);
            StringBuilder sb = new StringBuilder();

            String line = null;
            while ((line = reader.readLine()) != null)
            {
                sb.append(line + "\n");
            }
            result = sb.toString();
        } catch (Exception e) {
            // Oops
        }
        finally {
            try{if(inputStream != null)inputStream.close();}catch(Exception squish){}
        }
        return result;
    }

    @Override
    protected void onPostExecute(String result){
        myJSON=result;
        showList2();
    }
}

Une idée de quelle autre méthode devrais-je utiliser à la place? Ou de préférence comment je devrais modifier celui-ci pour travailler et des idées pourquoi mon AsyncTask ne démarre jamais?

EDIT: J'ai appliqué toutes les suggestions mentionnées ci-dessous et malheureusement aucune ne fonctionne jusqu'à présent (mon AsyncTask ne démarre toujours pas).

Et une autre question: utiliser plus d'un AsyncTask dans la même activité a quelque chose à voir avec mon problème?

24
Diana

Puisque (je suppose) aucune des autres solutions suggérées ne fonctionne, je soupçonne que votre problème réside dans la façon dont les AsyncTask sont exécutés. Si plusieurs AsyncTasks s'exécutent dans la même activité, comme dans votre application, ces AsyncTasks ne s'exécuteront pas en parallèle. Ils s'exécuteront l'un après l'autre.

Je soupçonne que vos autres tâches AsyncTask sont longues, de sorte que votre GetDataJSON AsyncTask attend la fin des autres tâches.

La solution consiste à activer l'exécution parallèle d'AsyncTask. Utilisez le code suivant pour exécuter AsyncTasks en parallèle.

GetDataJSON g = new GetDataJSON();
g.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

Depuis les documents AsyncTask:

Ordre d'exécution

Lors de leur introduction, les tâches AsyncTasks ont été exécutées en série sur un seul thread d'arrière-plan. À partir de DONUT, cela a été changé en un pool de threads permettant à plusieurs tâches de fonctionner en parallèle. À partir de HONEYCOMB, les tâches sont exécutées sur un seul thread pour éviter les erreurs d'application courantes causées par l'exécution parallèle.

Si vous voulez vraiment une exécution parallèle, vous pouvez appeler executeOnExecutor (Java.util.concurrent.Executor, Object []) avec THREAD_POOL_EXECUTOR.

J'espère que cela t'aides.

23
DavidH

il suffit de changer vos paramètres asynctask

 class GetDataJSON extends AsyncTask<String, Void, String>

à,

 class GetDataJSON extends AsyncTask<Void, Void, String>
10
Mayur R. Amipara

À partir de votre question, j'ai conclu que vous essayez d'obtenir la liste d'amis du serveur et en fonction du résultat, vous afficherez le message Toast.

Selon votre code, vous ne créez pas et n'affichez pas le AlertDialog à partir de alertDialogBuilder. Essayez d'afficher la AlertBox.

Comme AsyncTask s'exécute dans un thread séparé. D'où le

if (friends.contains(friend)) 

s'exécutera immédiatement après

 g.execute();

Ainsi, même l'utilisateur est dans la liste d'amis, il affichera le Toast de la partie else.

De plus, vous n'avez pas mis les journaux dans les méthodes Asynctask, cela pourrait vous donner l'impression qu'AsyncTask n'est pas en cours d'exécution.

Je vous suggère de déplacer votre code de condition if de AlertDialog vers onPostExecute() méthode de la GetDataJSON et de le mettre après showList2(); . Mettez également quelques journaux dans les méthodes AsyncTask.

J'espère que cela vous aidera. Veuillez trouver le code ci-dessous pour votre référence:

public class AIssue extends Activity {
String result = " DATA";

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.some);
    findViewById(R.id.button1).setOnClickListener(
            new View.OnClickListener() {

                @Override
                public void onClick(View arg0) {
                    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
                            .permitAll().build();
                    StrictMode.setThreadPolicy(policy);

                    AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
                            AIssue.this);
                    alertDialogBuilder.setCancelable(false);
                    alertDialogBuilder.setPositiveButton("OK",
                            new DialogInterface.OnClickListener() {

                                @Override
                                public void onClick(DialogInterface dialog,
                                        int which) {
                                    GetDataJSON g = new GetDataJSON();
                                    g.execute();

                                }
                            });
                    alertDialogBuilder.create().show();
                }
            });
}

// Getting the users
private class GetDataJSON extends AsyncTask<Void, Void, String> {
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        Log.e("IN", "ONPRE EXECUTE");
    }

    @Override
    protected String doInBackground(Void... params) {
        String result = "SOME DATA";
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(1000);
                Log.e("IN", "DO IN BACKGROUND");
            } catch (InterruptedException e) {
                e.printStackTrace();
                result = "ERROR";
            }

        }
        return result;
    }

    @Override
    protected void onPostExecute(String result) {
        Log.e("IN", "ON POST EXECUTE");
        Log.e("IN", "" + result);
        /*****
         * Your Condition to Check The Friend should be here after
         * showList2();
         * ***/
        if (result.equalsIgnoreCase("SOME DATA"))// replace it with your
                                                    // condition to check
                                                    // friends
        {
            Log.e("IN", "IF");
        } else {
            Log.e("IN", "ELSE");
        }
    }
}
}
8
avinash

Dans la méthode getData2 (), essayez ceci:

new AsyncTask<String, Void, String> {
        @Override
        protected String doInBackground(String... params) {
            // your code
        }

        @Override
        protected void onPostExecute(String result){
           // your code
        }
    }.execute();

ou si cela ne fonctionne pas, mettez la classe AsyncTask en dehors de la méthode, puis passez directement un appel pour exécuter la classe AsyncTask au lieu de getData2 (), comme ceci

new GetDataJSON().execute();
4
techroid

ajoutez cette méthode de remplacement dans la tâche Aysc.

 @Override
        protected void onPreExecute() {
            super.onPreExecute();

        }

Je ne sais pas ce que vous essayez de faire ici, mais ce code s'exécutera avant la fin de la tâche asynchrone.

if (friends.contains(friend)) // if you are already friends with that user
                                        Toast.makeText(getApplicationContext(), "You are already friends with that user!",
                                                Toast.LENGTH_LONG).show();
                                    else {
                                        if (!users.contains(friend)) // the user doesn't exist in our database
                                            Toast.makeText(getApplicationContext(), "That user doesn't exist! You either haven't introduced the right email or he's not a registered user within Poinder.",
                                                    Toast.LENGTH_LONG).show();
                                        else // the user exists so we add him to the friends list
                                        {
                                            //do something
                                        }

Si vous voulez que ce code s'exécute après la fin de votre tâche asyc, ajoutez ce code dans la méthode ur showList2 ().

Au fait, pourquoi créer une tâche asynchrone dans la méthode interne. C'est une mauvaise idée. Créez une tâche aynch distincte. afin que vous puissiez utiliser d'une autre activité.

3
chaitanya dalvi

Je ne pense pas que forcer le mode strict aide dans cette situation. Vous devez utiliser AsyncTask au lieu du mode strict lors du codage des opérations réseau (comme celles que vous faites dans la méthode doInBackground) afin que votre interface utilisateur ne soit pas bloquée.

Le mode strict force l'exécution des opérations sur le thread principal de l'application, tandis que AsyncTask s'exécute sur un thread d'arrière-plan.

3
user3641702

Ajouter un constructeur sur AsyncTask

public GetDataJSON (){
}

Ajoutez son onPreExecute pour être plus sûr

@Override
    protected void onPreExecute() {
    super.onPreExecute();
    Toast.makeText(this /*or getActivity()*/,"IT'S WORKING!!!", Toast.LENGTH_LONG).show();

    }
3
Sheychan

Le problème vient de vos paramètres asynctask

La documentation de Google Android indique que:

Une tâche asynchrone est définie par 3 types génériques, appelés Params, Progression et Résultat, et 4 étapes, appelées onPreExecute, doInBackground, onProgressUpdate et onPostExecute.

Types génériques d'AsyncTask:

Les trois types utilisés par une tâche asynchrone sont les suivants:

La documentation de Google Android indique que:

Types génériques d'AsyncTask:

Les trois types utilisés par une tâche asynchrone sont les suivants:

  1. Params, le type des paramètres envoyés à la tâche lors de l'exécution.
  2. Progression, type des unités de progression publiées lors du calcul en arrière-plan.
  3. Résultat, le type du résultat du calcul d'arrière-plan.

Tous les types ne sont pas toujours utilisés par une tâche asynchrone. Pour marquer un type comme inutilisé, utilisez simplement le type Void:

 private class MyTask extends AsyncTask<Void, Void, Void> { ... }

Donc, comme vous n'envoyez aucun paramètre à la tâche AsyncTask, faites votre tâche asynchrone comme ci-dessous

 // Getting the users
    public void getData2(){
   new GetDataJSON().execute();  
    }


class GetDataJSON extends AsyncTask<Void, Void, String> {

            @Override
            protected String doInBackground(Void... params) {
                /// your logic here
                return result;
            }

            @Override
            protected void onPostExecute(String result){
                // your logic here
            }
        }
2
King of Masses

Une solution à ce problème, assez habituelle, que j'ai introduite dans mon développement actuel est AsyncService, je n'utiliserai pas toutes les fonctionnalités de cette bibliothèque (le système Ache) mais elle est puissante et elle vous aide également à nettoyer le code dans vos activités.

  1. Vous déclarez votre service, qui va récupérer des données, avec l'annotation @AsyncService
  2. Vous injectez le service dans votre activité
  3. Appelez votre service partout où vous en avez besoin
  4. Déclarez une méthode au sein de votre activité avec l'annotation @OnMessage où vous allez traiter la réponse du service ...

Wiki AsyncService GitHub

Je ne sais pas s'il existe une autre solution qui aide les développeurs à séparer les préoccupations et à nettoyer le code (en Android je veux dire) comme ça, c'est le meilleur que j'ai essayé et peut-être devriez-vous lui donner un essayez aussi. Cela vous aidera à résoudre votre problème actuel.

J'espère que cela aide.

2
Juan