Comment obtenir le résultat de OnPostExecute () pour l'activité principale car AsyncTask est une classe séparée?

j'ai ces deux classes. Mon activité principale et celle qui étend le AsyncTask , maintenant dans mon activité principale je dois obtenir le résultat du OnPostExecute() dans le AsyncTask . Comment puis-je transmettre ou obtenir le résultat de mon Activité principale?

Voici les codes de l'échantillon.

mon activité principale.

public class MainActivity extends Activity{

    AasyncTask asyncTask = new AasyncTask();

    @Override
    public void onCreate(Bundle aBundle) {
        super.onCreate(aBundle);            

        //Calling the AsyncTask class to start to execute.  
        asyncTask.execute(a.targetServer); 

        //Creating a TextView.
        TextView displayUI = asyncTask.dataDisplay;
        displayUI = new TextView(this);
        this.setContentView(tTextView); 
    }

}

c'est la classe AsyncTask

public class AasyncTask extends AsyncTask<String, Void, String> {

TextView dataDisplay; //store the data  
String soapAction = "http://sample.com"; //SOAPAction header line. 
String targetServer = "https://sampletargeturl.com"; //Target Server.

//SOAP Request.
String soapRequest = "<sample XML request>";    



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

String responseStorage = null; //storage of the response

try {


    //Uses URL and HttpURLConnection for server connection. 
    URL targetURL = new URL(targetServer);
    HttpURLConnection httpCon = (HttpURLConnection) targetURL.openConnection();
    httpCon.setDoOutput(true);
    httpCon.setDoInput(true);
    httpCon.setUseCaches(false); 
    httpCon.setChunkedStreamingMode(0);

    //properties of SOAPAction header
    httpCon.addRequestProperty("SOAPAction", soapAction);
    httpCon.addRequestProperty("Content-Type", "text/xml; charset=utf-8"); 
    httpCon.addRequestProperty("Content-Length", "" + soapRequest.length());
    httpCon.setRequestMethod(HttpPost.METHOD_NAME);


    //sending request to the server.
    OutputStream outputStream = httpCon.getOutputStream(); 
    Writer writer = new OutputStreamWriter(outputStream);
    writer.write(soapRequest);
    writer.flush();
    writer.close();


    //getting the response from the server
    InputStream inputStream = httpCon.getInputStream(); 
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
    ByteArrayBuffer byteArrayBuffer = new ByteArrayBuffer(50);

    int intResponse = httpCon.getResponseCode();

    while ((intResponse = bufferedReader.read()) != -1) {
        byteArrayBuffer.append(intResponse);
    }

    responseStorage = new String(byteArrayBuffer.toByteArray()); 

    } catch (Exception aException) {
    responseStorage = aException.getMessage(); 
    }
    return responseStorage;
}

protected void onPostExecute(String result) {

    aTextView.setText(result);

}       

}   
299
demandé sur God 2012-09-25 05:26:26

14 réponses

facile:

  1. Créer interface catégorie", où String output est facultative, ou peut-être ce que les variables que vous souhaitez retourner.

    public interface AsyncResponse {
        void processFinish(String output);
    }
    
  2. allez dans votre classe AsyncTask et déclarez l'interface AsyncResponse comme un champ:

    public class MyAsyncTask extends AsyncTask<Void, Void, String> {
      public AsyncResponse delegate = null;
    
        @Override
        protected void onPostExecute(String result) {
          delegate.processFinish(result);
        }
     }
    
  3. dans votre activité principale, vous avez besoin de implements interface AsyncResponse .

    public class MainActivity implements AsyncResponse{
      MyAsyncTask asyncTask =new MyAsyncTask();
    
      @Override
      public void onCreate(Bundle savedInstanceState) {
    
         //this to set delegate/listener back to this class
         asyncTask.delegate = this;
    
         //execute the async task 
         asyncTask.execute();
      }
    
      //this override the implemented method from asyncTask
      @Override
      void processFinish(String output){
         //Here you will receive the result fired from async class 
         //of onPostExecute(result) method.
       }
     }
    

mise à jour

Je ne savais pas que c'était une de vos préférées. Voici donc la façon simple et pratique d'utiliser interface .

utilise toujours le même interface . Pour votre information, vous pouvez combiner cela dans la classe AsyncTask .

dans AsyncTask classe:

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

  // you may separate this or combined to caller class.
  public interface AsyncResponse {
        void processFinish(String output);
  }

  public AsyncResponse delegate = null;

    public MyAsyncTask(AsyncResponse delegate){
        this.delegate = delegate;
    }

    @Override
    protected void onPostExecute(String result) {
      delegate.processFinish(result);
    }
}

faites ceci dans votre classe Activity

public class MainActivity extends Activity {

   MyAsyncTask asyncTask = new MyAsyncTask(new AsyncResponse(){

     @Override
     void processFinish(String output){
     //Here you will receive the result fired from async class 
     //of onPostExecute(result) method.
     }
  }).execute();

 }

Ou, de la mise en œuvre de l'interface sur la reprise de l'Activité

public class MainActivity extends Activity 
    implements AsyncResponse{

    @Override
    public void onCreate(Bundle savedInstanceState) {

        //execute the async task 
        new MyAsyncTask(this).execute();
    }

    //this override the implemented method from AsyncResponse
    @Override
    void processFinish(String output){
        //Here you will receive the result fired from async class 
        //of onPostExecute(result) method.
    }
}

comme vous pouvez voir 2 solutions ci-dessus, la première et la troisième, il a besoin de créer la méthode processFinish , l'autre, la méthode est à l'intérieur du paramètre appelant. La troisième est plus soignée parce qu'il n'y a pas de classe anonyme emboîtée. Espérons que cette aide

Tip : changement String output , String response , et String result correspondant à différents types afin d'obtenir différents objets.

647
répondu HelmiB 2018-04-22 12:05:51

il y a quelques options:

  • nid de la classe AsyncTask dans votre classe Activity . En supposant que vous n'utilisez pas la même tâche dans plusieurs activités, c'est la façon la plus facile. Tout votre code reste le même, vous déplacez simplement la classe de tâche existante pour être une classe imbriquée dans la classe de votre activité.

    public class MyActivity extends Activity {
        // existing Activity code
        ...
    
        private class MyAsyncTask extends AsyncTask<String, Void, String> {
            // existing AsyncTask code
            ...
        }
    }
    
  • créez un constructeur sur mesure pour votre AsyncTask qui prend un référence à votre Activity . Vous instanciez la tâche avec quelque chose comme new MyAsyncTask(this).execute(param1, param2) .

    public class MyAsyncTask extends AsyncTask<String, Void, String> {
        private Activity activity;
    
        public MyAsyncTask(Activity activity) {
            this.activity = activity;
        }
    
        // existing AsyncTask code
        ...
    }
    
22
répondu user113215 2015-02-24 02:29:05

j'ai senti que l'approche ci-dessous est très facile.

j'ai déclaré une interface pour le rappel

public interface AsyncResponse {
    void processFinish(Object output);
}

a alors créé une tâche asynchrone pour répondre à tous les types de demandes parallèles

 public class MyAsyncTask extends AsyncTask<Object, Object, Object> {

    public AsyncResponse delegate = null;//Call back interface

    public MyAsyncTask(AsyncResponse asyncResponse) {
        delegate = asyncResponse;//Assigning call back interfacethrough constructor
    }

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

      //My Background tasks are written here

      return {resutl Object}

    }

    @Override
    protected void onPostExecute(Object result) {
        delegate.processFinish(result);
    }

}

a ensuite appelé la tâche asynchrone en cliquant sur un bouton dans la classe d'activité.

public class MainActivity extends Activity{

    @Override
    public void onCreate(Bundle savedInstanceState) {

    Button mbtnPress = (Button) findViewById(R.id.btnPress);

    mbtnPress.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                MyAsyncTask asyncTask =new MyAsyncTask(new AsyncResponse() {

                    @Override
                    public void processFinish(Object output) {
                        Log.d("Response From Asynchronous task:", (String) output);

                        mbtnPress.setText((String) output);
                   }
                });

                asyncTask.execute(new Object[] { "Your request to aynchronous task class is giving here.." });


            }
        });

    }



}

Merci

14
répondu Arshad 2017-06-23 21:23:19

Vous pouvez essayer ce code dans votre classe Principale. Cela a fonctionné pour moi, mais j'ai mis en œuvre des méthodes d'une autre manière

try {
    String receivedData = new AsyncTask().execute("http://yourdomain.com/yourscript.php").get();
} 
catch (ExecutionException | InterruptedException ei) {
    ei.printStackTrace();
}
13
répondu Nicu P 2015-05-27 14:23:41

vous pouvez le faire en quelques lignes, il suffit de surcharger onPostExecute lorsque vous appelez votre AsyncTask. Voici un exemple pour vous:

new AasyncTask()
{
    @Override public void onPostExecute(String result)
    {
       // do whatever you want with result 
    }
}.execute(a.targetServer);

j'espère que cela vous a aidé, heureux codding :)

6
répondu Sa Qada 2015-03-17 16:00:41

dans votre Oncreate():

`

myTask.execute("url");
String result = "";
try {
      result = myTask.get().toString();
} catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
}catch (ExecutionException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();

}

5
répondu user3691697 2014-05-30 14:43:46

pourquoi les gens rendent ça si difficile.

cela devrait suffire.

Ne pas mettre en œuvre la onPostExecute sur la async tâche plutôt mettre en œuvre de l'Activité:

public class MainActivity extends Activity 
{

@Override
public void onCreate(Bundle savedInstanceState) {

    //execute the async task 
    MyAsyncTask task = new MyAsyncTask(){
            protected void onPostExecute(String result) {
                //Do your thing
            }       

    }

    task.execute("Param");

}


}
4
répondu bugdayci 2017-07-26 19:12:04

cette réponse pourrait être tardive mais je voudrais mentionner quelques choses lorsque votre Activity dépend de AsyncTask . Cela vous aiderait à prévenir les accidents et la gestion de la mémoire. Comme déjà mentionné dans les réponses ci-dessus vont avec interface , nous les disons aussi callbacks. Ils travailleront comme un indicateur, mais jamais envoyer fort référence de Activity ou interface toujours utiliser faible référence dans ces cas.

s'il vous Plaît se référer à la capture d'écran ci-dessous pour trouver comment qui peuvent provoquer des problèmes.

enter image description here

comme vous pouvez voir si nous avons commencé AsyncTask avec un fort référence alors il n'y a aucune garantie que notre Activity / Fragment sera vivant jusqu'à ce que nous obtenions des données, il serait donc préférable d'utiliser WeakReference dans ces cas et cela aidera également dans la gestion de la mémoire que nous ne tiendrons jamais la référence forte de notre Activity alors il sera admissible à la collecte des ordures après sa distorsion.

cochez ci - dessous le code snippet pour savoir comment utiliser awesome weakref -

MyTaskInformer.java Interface qui fonctionnera comme un indicateur.

public interface MyTaskInformer {

    void onTaskDone(String output);

}

MySmallAsyncTask.java AsyncTask de faire de longues tâches en cours d'exécution, qui va l'utiliser WeakReference .

public class MySmallAsyncTask extends AsyncTask<String, Void, String> {

    // ***** Hold weak reference *****
    private WeakReference<MyTaskInformer> mCallBack;

    public MySmallAsyncTask(MyTaskInformer callback) {
        this.mCallBack = new WeakReference<>(callback);
    }

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

        // Here do whatever your task is like reading/writing file
        // or read data from your server or any other heavy task

        // Let us suppose here you get response, just return it
        final String output = "Any out, mine is just demo output";

        // Return it from here to post execute
        return output;
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);

        // Here you can't guarantee that Activity/Fragment is alive who started this AsyncTask

        // Make sure your caller is active

        final MyTaskInformer callBack = mCallBack.get();

        if(callBack != null) {
            callBack.onTaskDone(s);
        }
    }
}

MainActivity.java cette classe est utilisée pour commencer mon AsyncTask implémenter interface sur cette classe et override cette méthode obligatoire.

public class MainActivity extends Activity implements MyTaskInformer {

    private TextView mMyTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mMyTextView = (TextView) findViewById(R.id.tv_text_view);

        // Start your AsyncTask and pass reference of MyTaskInformer in constructor
        new MySmallAsyncTask(this).execute();
    }

    @Override
    public void onTaskDone(String output) {

        // Here you will receive output only if your Activity is alive.
        // no need to add checks like if(!isFinishing())

        mMyTextView.setText(output);
    }
}
4
répondu Rahul 2017-08-04 07:36:35

vous pouvez appeler la get() méthode de AsyncTask (ou la surcharge get(long, TimeUnit) ). Cette méthode bloquera jusqu'à ce que le AsyncTask ait terminé son travail, auquel point il vous retournera le Result .

il serait sage de faire un autre travail entre la création/début de votre tâche async et l'appel de la méthode get , sinon vous n'utilisez pas la tâche async très efficacement.

4
répondu nicholas.hauschild 2017-09-26 13:11:21

Salut Vous pouvez faire quelque chose comme ceci:

  1. Créer une classe qui implémente l'AsyncTask

    // TASK 
    public class SomeClass extends AsyncTask<Void, Void, String>>
    {
    
        private OnTaskExecutionFinished _task_finished_event;
    
        public interface OnTaskExecutionFinished
        {
            public void OnTaskFihishedEvent(String Reslut);
        }
    
        public void setOnTaskFinishedEvent(OnTaskExecutionFinished _event)
        {
            if(_event != null)
            {
                this._task_finished_event = _event;
            }
        }
    
        @Override
        protected void onPreExecute()
        {
            super.onPreExecute();
    
        }
    
        @Override
        protected String doInBackground(Void... params)
        {
            // do your background task here ...
    
            return "Done!";
        }
    
        @Override
        protected void onPostExecute(String result)
        {
            super.onPostExecute(result);
            if(this._task_finished_event != null)
            {
                this._task_finished_event.OnTaskFihishedEvent(result);
            }
            else
            {
                Log.d("SomeClass", "task_finished even is null");
            }
        }
    }
    
  2. ajouter dans L'activité principale

    // MAIN ACTIVITY
    public class MyActivity extends ListActivity
    {
       ...
        SomeClass _some_class = new SomeClass();
        _someclass.setOnTaskFinishedEvent(new _some_class.OnTaskExecutionFinished()
        {
        @Override
        public void OnTaskFihishedEvent(String result)
        {
            Toast.makeText(getApplicationContext(),
                    "Phony thread finished: " + result,
                    Toast.LENGTH_SHORT).show();
        }
    
       });
       _some_class.execute();
       ...
     }
    
2
répondu Oleg Karbushev 2014-07-23 23:13:31

Vous pouvez écrire votre propre écouteur. C'est comme HelmiB 'S réponse mais semble plus naturel:

créer interface d'écoute:

public interface myAsyncTaskCompletedListener {
    void onMyAsynTaskCompleted(int responseCode, String result);
}

alors écrivez votre tâche asynchrone:

public class myAsyncTask extends AsyncTask<String, Void, String> {

    private myAsyncTaskCompletedListener listener;
    private int responseCode = 0;

    public myAsyncTask() {
    }

    public myAsyncTask(myAsyncTaskCompletedListener listener, int responseCode) {
        this.listener = listener;
        this.responseCode = responseCode;
    }

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


    @Override
    protected String doInBackground(String... params) {
        String result;
        String param = (params.length == 0) ? null : params[0];
        if (param != null) {
            // Do some background jobs, like httprequest...
            return result;
        }
        return null;
    }

    @Override
    protected void onPostExecute(String finalResult) {
        super.onPostExecute(finalResult);
        if (!isCancelled()) {
            if (listener != null) {
                listener.onMyAsynTaskCompleted(responseCode, finalResult);
            }
        }
    }
}

enfin mettre en œuvre auditeur en activité:

public class MainActivity extends AppCompatActivity implements myAsyncTaskCompletedListener {

    @Override
    public void onMyAsynTaskCompleted(int responseCode, String result) {

        switch (responseCode) {
            case TASK_CODE_ONE: 
                // Do something for CODE_ONE
                break;
            case TASK_CODE_TWO:
                // Do something for CODE_TWO
                break;
            default: 
                // Show some error code
        }        
    }

Et voici comment vous pouvez appeler asyncTask:

 protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Some other codes...
        new myAsyncTask(this,TASK_CODE_ONE).execute("Data for background job");
        // And some another codes...
}
2
répondu Kuvalya 2017-05-23 12:02:50

Créer un membre statique dans votre classe d'Activité. Puis attribuer la valeur pendant le onPostExecute

par exemple, si le résultat de votre AsyncTask est une chaîne, créez une chaîne statique publique dans votre activité""

public static String dataFromAsyncTask;

puis, dans le onPostExecute de L'AsyncTask, il suffit de faire un appel statique à votre classe principale et de définir la valeur.

MainActivity.dataFromAsyncTask = "result blah";

1
répondu mrres1 2012-09-25 01:38:08

je le fais fonctionner en utilisant threading et handler/message. Les étapes à suivre: Déclarer un dialogue de progrès

ProgressDialog loadingdialog;

crée une fonction pour fermer le dialogue lorsque l'opération est terminée.

   private Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        loadingdialog.dismiss();

    }
    };

coder vos détails D'exécution:

 public void startUpload(String filepath) {
    loadingdialog = ProgressDialog.show(MainActivity.this, "Uploading", "Uploading Please Wait", true);
    final String _path = filepath;
    new Thread() {
        public void run() {
            try {
                UploadFile(_path, getHostName(), getPortNo());
                handler.sendEmptyMessage(0);

            } catch (Exception e) {
                Log.e("threadmessage", e.getMessage());
            }
        }
    }.start();
}
0
répondu RAY 2016-10-09 13:37:06

vous devez utiliser " protocoles pour déléguer ou fournir des données au AsynTask .

délégués et sources de données

un délégué est un objet qui agit au nom ou en coordination avec un autre objet lorsque cet objet rencontre un événement dans un programme. ( Apple définition de )

Les protocoles

et sont des interfaces qui méthodes pour déléguer certains comportements.

Voici un exemple complet!!!

0
répondu IgniteCoders 2018-04-26 15:36:00