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);
}
}
14 réponses
facile:
-
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); }
-
allez dans votre classe
AsyncTask
et déclarez l'interfaceAsyncResponse
comme un champ:public class MyAsyncTask extends AsyncTask<Void, Void, String> { public AsyncResponse delegate = null; @Override protected void onPostExecute(String result) { delegate.processFinish(result); } }
-
dans votre activité principale, vous avez besoin de
implements
interfaceAsyncResponse
.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.
il y a quelques options:
-
nid de la classe
AsyncTask
dans votre classeActivity
. 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 à votreActivity
. Vous instanciez la tâche avec quelque chose commenew 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 ... }
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
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();
}
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 :)
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();
}
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");
}
}
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.
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);
}
}
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.
Salut Vous pouvez faire quelque chose comme ceci:
-
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"); } } }
-
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(); ... }
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...
}
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";
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();
}
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 protocoleset sont des interfaces qui méthodes pour déléguer certains comportements.