Je lisais à propos de AsyncTask
, et j'ai essayé le programme simple ci-dessous. Mais cela ne semble pas fonctionner. Comment puis-je le faire fonctionner?
public class AsyncTaskActivity extends Activity {
Button btn;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener((OnClickListener) this);
}
public void onClick(View view){
new LongOperation().execute("");
}
private class LongOperation extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
for(int i=0;i<5;i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed");
return null;
}
@Override
protected void onPostExecute(String result) {
}
@Override
protected void onPreExecute() {
}
@Override
protected void onProgressUpdate(Void... values) {
}
}
}
J'essaie simplement de changer l'étiquette après 5 secondes de traitement en arrière-plan.
C'est mon main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
Android:orientation="vertical" >
<ProgressBar
Android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:indeterminate="false"
Android:max="10"
Android:padding="10dip">
</ProgressBar>
<Button
Android:id="@+id/button1"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="Start Progress" >
</Button>
<TextView Android:id="@+id/output"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:text="Replace"/>
</LinearLayout>
Ok, vous essayez d'accéder à l'interface graphique via un autre thread. Ceci, dans l’ensemble, n’est pas une bonne pratique.
AsyncTask exécute tout ce qui se trouve dans doInBackground()
à l'intérieur d'un autre thread, qui n'a pas accès à l'interface graphique où se trouvent vos vues.
preExecute()
et postExecute()
vous offrent un accès à l'interface graphique avant et après le soulèvement important dans ce nouveau thread. Vous pouvez même transmettre le résultat de l'opération longue à postExecute()
pour afficher ensuite les résultats du traitement.
Voir ces lignes où vous mettez à jour ultérieurement votre TextView:
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed");
mettez-les dans PostExecute()
Vous verrez alors votre texte TextView mis à jour après la fin de la doInBackground
.
EDIT: J'ai remarqué que votre écouteur onClick ne vérifie pas quelle vue a été sélectionnée. Je trouve que le moyen le plus simple de procéder consiste à utiliser des instructions switch. J'ai un cours complet édité ci-dessous avec toutes les suggestions pour éviter la confusion.
import Android.app.Activity;
import Android.os.AsyncTask;
import Android.os.Bundle;
import Android.provider.Settings.System;
import Android.view.View;
import Android.widget.Button;
import Android.widget.TextView;
import Android.view.View.OnClickListener;
public class AsyncTaskActivity extends Activity implements OnClickListener {
Button btn;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn = (Button) findViewById(R.id.button1);
// because we implement OnClickListener we only have to pass "this"
// (much easier)
btn.setOnClickListener(this);
}
public void onClick(View view) {
// detect the view that was "clicked"
switch (view.getId()) {
case R.id.button1:
new LongOperation().execute("");
break;
}
}
private class LongOperation extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.interrupted();
}
}
return "Executed";
}
@Override
protected void onPostExecute(String result) {
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed"); // txt.setText(result);
// might want to change "executed" for the returned string passed
// into onPostExecute() but that is upto you
}
@Override
protected void onPreExecute() {}
@Override
protected void onProgressUpdate(Void... values) {}
}
}
Ma réponse complète est ici , mais voici une image explicative pour compléter les autres réponses sur cette page. Pour moi, comprendre où toutes les variables se dirigeaient était la partie la plus déroutante au début.
Je suis sûr qu'il s'exécute correctement, mais vous essayez de modifier les éléments de l'interface utilisateur dans le fil d'arrière-plan et cela ne suffira pas.
Révisez votre appel et AsyncTask comme suit:
Classe d'appel
Remarque: Je suggère personnellement d'utiliser onPostExecute()
partout où vous exécutez votre thread AsyncTask et non dans la classe qui étend AsyncTask elle-même. Je pense que cela rend le code plus facile à lire, en particulier si vous avez besoin de la AsyncTask à plusieurs endroits pour traiter les résultats légèrement différemment.
new LongThread()
{
@Override public void onPostExecute(String result)
{
TextView txt = (TextView) findViewById(R.id.output);
txt.setText(result);
}
}.execute("");
Classe LongThread (étend AsyncTask):
@Override
protected String doInBackground(String... params) {
for(int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "Executed";
}
J'ai créé un exemple simple d'utilisation d'AsyncTask d'Android. Cela commence par onPreExecute(), doInBackground(), publishProgress()
et enfin onProgressUpdate()
.
Dans ce doInBackground () fonctionne comme un fil d’arrière-plan, alors que d’autres fonctionnent dans le thread UI. Vous ne pouvez pas accéder à un élément d'interface utilisateur dans doInBackground (). La séquence est la même que celle que j'ai mentionnée.
Toutefois, si vous devez mettre à jour un widget à partir de doInBackground
, vous pouvez publishProgress
à partir de doInBackground
qui appellera onProgressUpdate
pour mettre à jour votre widget d'interface utilisateur.
class TestAsync extends AsyncTask<Void, Integer, String>
{
String TAG = getClass().getSimpleName();
protected void onPreExecute (){
super.onPreExecute();
Log.d(TAG + " PreExceute","On pre Exceute......");
}
protected String doInBackground(Void...arg0) {
Log.d(TAG + " DoINBackGround","On doInBackground...");
for(int i=0; i<10; i++){
Integer in = new Integer(i);
publishProgress(i);
}
return "You are at PostExecute";
}
protected void onProgressUpdate(Integer...a){
super.onProgressUpdate(a);
Log.d(TAG + " onProgressUpdate", "You are in progress update ... " + a[0]);
}
protected void onPostExecute(String result) {
super.onPostExecute(result);
Log.d(TAG + " onPostExecute", "" + result);
}
}
Appelez ça comme ça dans votre activité:
new TestAsync().execute();
Déplacez ces deux lignes:
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed");
sur la méthode doInBackground
de votre AsyncTask et mettez-les dans la méthode onPostExecute
. Votre AsyncTask
devrait ressembler à ceci:
private class LongOperation extends AsyncTask<String, Void, String> {
@Override
protected String doInBackground(String... params) {
try {
Thread.sleep(5000); // no need for a loop
} catch (InterruptedException e) {
Log.e("LongOperation", "Interrupted", e);
return "Interrupted";
}
return "Executed";
}
@Override
protected void onPostExecute(String result) {
TextView txt = (TextView) findViewById(R.id.output);
txt.setText(result);
}
}
Lorsqu'une tâche asynchrone est exécutée, la tâche passe par 4 étapes:
Ci-dessous un exemple de démonstration
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
et une fois que vous avez créé, une tâche est exécutée très simplement:
new DownloadFilesTask().execute(url1, url2, url3);
J'espère que cela t'aidera...
Le plus court exemple pour faire quelque chose de manière asynchrone:
class MyAsyncTask extends Android.os.AsyncTask {
@Override
protected Object doInBackground(Object[] objects) {
//do something asynchronously
return null;
}
}
Pour l'exécuter:
(new MyAsyncTask()).execute();
Lorsque vous êtes dans le thread de travail, vous ne pouvez pas manipuler directement les éléments de l'interface utilisateur sur Android.
Lorsque vous utilisez AsyncTask, veuillez comprendre les méthodes de rappel.
Par exemple:
public class MyAyncTask extends AsyncTask<Void, Void, Void>{
@Override
protected void onPreExecute() {
// Here you can show progress bar or something on the similar lines.
// Since you are in a UI thread here.
super.onPreExecute();
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
// After completing execution of given task, control will return here.
// Hence if you want to populate UI elements with fetched data, do it here.
}
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
// You can track you progress update here
}
@Override
protected Void doInBackground(Void... params) {
// Here you are in the worker thread and you are not allowed to access UI thread from here.
// Here you can perform network operations or any heavy operations you want.
return null;
}
}
FYI: Pour accéder au fil de l'interface utilisateur à partir d'un fil de travail, vous utilisez la méthode runOnUiThread () ou la méthode post de votre vue.
Par exemple:
runOnUiThread(new Runnable() {
textView.setText("something.");
});
or
yourview.post(new Runnable() {
yourview.setText("something");
});
Cela vous aidera à mieux connaître les choses. Par conséquent, dans votre cas, vous devez définir votre textview dans la méthode onPostExecute ().
Ne pas
Si vous êtes nouveau dans AsyncTask, il est très courant d’être dérouté lors de l’écriture d’une AsyncTask. Les principaux responsables sont les paramètres utilisés dans la AsyncTask ie AsyncTask<A,B,C>
. Sur la base de la signature A, B, C (arguments) des méthodes diffère, ce qui rend les choses encore plus confuses.
La clé est ne pas mémoriser. Si vous pouvez visualiser ce que votre tâche doit réellement faire, alors écrire la tâche asynchrone avec la signature correcte du premier coup serait un jeu d'enfant. Déterminez simplement ce que sont vos intrants, vos progrès et vos résultats et vous serez prêt à partir.
AsyncTask sont des tâches en arrière-plan qui s'exécutent dans le thread en arrière-plan. Cela prend un Input, exécute Progress et donne Output.
ie
AsyncTask<Input,Progress,Output>
.
Entre
AsyncTask
etdoInBackground()
doInBackground()
etonPostExecute(),
onProgressUpdate () `sont également en relation
Comment écrire ça dans le code?
DownloadTask extends AsyncTask<String,Integer,String>{
// Always same signature
@Override
public void onPreExecute()
{}
@Override
public String doInbackGround(String... params)
{
// Download code
int downloadPerc = // calculate that
publish(downloadPerc);
return "Download Success";
}
@Override
public void onPostExecute(String result)
{
super.onPostExecute(result);
}
@Override
public void onProgressUpdate(Integer... params)
{
// show in spinner, access UI elements
}
}
Comment allez-vous exécuter cette tâche?
new DownLoadTask().execute("Paradise.mp3");
Je vous recommanderais de vous simplifier la vie en utilisant cette bibliothèque pour les travaux en tâche de fond https://github.com/Arasthel/AsyncJobLibrary
c'est aussi simple ..
AsyncJob.doInBackground(new AsyncJob.OnBackgroundJob() {
@Override
public void doOnBackground() {
startRecording();
}
});
Didacticiel détaillé sur les tâches asynchrones
Qu'est-ce que AsyncTask?
AsyncTask est une classe Android qui nous aide à effectuer des opérations complexes telles que
Cela soulage la tension des développeurs de
Si vous
AsyncTask n'est pas une meilleure option pour vous. AsyncTask principalement utilisé pour des opérations courtes (quelques secondes au maximum)
Comment utiliser AsyncTask dans votre application?
AsyncTask utilise les types de données Generics
AsyncTask nous aide à mettre à jour l'interface utilisateur dans leurs méthodes.
Ces méthodes s'exécutent sur le thread principal. C'est pourquoi vous pouvez mettre à jour les éléments de l'interface utilisateur.
Ajoutez votre tâche difficile dans doInBackgrund ()
et appelez AsyncTask en utilisant execute () method.
Lien tutoriel détaillé complet ci-dessous
Exemple de tâche async avec la demande POST:
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair("key1", "value1"));
params.add(new BasicNameValuePair("key1", "value2"));
new WEBSERVICEREQUESTOR(URL, params).execute();
class WEBSERVICEREQUESTOR extends AsyncTask<String, Integer, String>
{
String URL;
List<NameValuePair> parameters;
private ProgressDialog pDialog;
public WEBSERVICEREQUESTOR(String url, List<NameValuePair> params)
{
this.URL = url;
this.parameters = params;
}
@Override
protected void onPreExecute()
{
pDialog = new ProgressDialog(LoginActivity.this);
pDialog.setMessage("Processing Request...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
super.onPreExecute();
}
@Override
protected String doInBackground(String... params)
{
try
{
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpEntity httpEntity = null;
HttpResponse httpResponse = null;
HttpPost httpPost = new HttpPost(URL);
if (parameters != null)
{
httpPost.setEntity(new UrlEncodedFormEntity(parameters));
}
httpResponse = httpClient.execute(httpPost);
httpEntity = httpResponse.getEntity();
return EntityUtils.toString(httpEntity);
} catch (Exception e)
{
}
return "";
}
@Override
protected void onPostExecute(String result)
{
pDialog.dismiss();
try
{
}
catch (Exception e)
{
}
super.onPostExecute(result);
}
}
Simplement:
LongOperation MyTask = new LongOperation();
MyTask.execute();
private class AsyncTaskDemo extends AsyncTask<Void, Void, Void> {
@Override
protected void onPreExecute() {
super.onPreExecute();
// Showing progress dialog
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Loading...");
progressDialog.setCancelable(false);
progressDialog.show();
}
@Override
protected Void doInBackground(Void... arg0) {
//do code here
return null;
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// Dismiss the progress dialog
if (progressDialog.isShowing()) {
progressDialog.dismiss();
}
}
@Override
protected void onCancelled() {
super.onCancelled();
progressDialog.dismiss();
Toast toast = Toast.makeText(getActivity(),
"Error is occured due to some probelm", Toast.LENGTH_LONG);
toast.setGravity(Gravity.TOP, 25, 400);
toast.show();
}
}
Vous devez déclarer le bouton onclicklistener. Une fois que vous avez cliqué dessus, la classe AsyncTask DownloadJson est appelée, le processus est indiqué ci-dessous:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new DownloadJson().execute();
}
});
}
// DownloadJSON AsyncTask
private class DownloadJson extends AsyncTask<Void, Void, Void> {
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected Void doInBackground(Void... params) {
newlist = new ArrayList<HashMap<String, String>>();
json = jsonParser.makeHttpRequest(json, "POST");
try {
newarray = new JSONArray(json);
for (int i = 0; i < countdisplay; i++) {
HashMap<String, String> eachnew = new HashMap<String, String>();
newobject = newarray.getJSONObject(i);
eachnew.put("id", newobject.getString("ID"));
eachnew.put("name", newobject.getString("Name"));
newlist.add(eachnew);
}
}
} catch (JSONException e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void args) {
newlisttemp.addAll(newlist);
NewAdapterpager newadapterpager = new NewAdapterpager(ProcesssActivitypager.this,newlisttemp);
newpager.setAdapter(newadapterpager);
}
}
Changez votre code comme indiqué ci-dessous:
@Override
protected void onPostExecute(String result) {
runOnUiThread(new Runnable() {
public void run() {
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("Executed");
}
});
}
Lorsque vous travaillez avec AsyncTask, il est nécessaire de créer un successeur de classe et d’enregistrer l’implémentation des méthodes nécessaires. Dans cette leçon, nous allons examiner trois méthodes:
doInBackground - sera exécuté dans un nouveau thread, ici nous résolvons toutes nos tâches difficiles. Parce que le fil non principal - n'a pas accès à l'interface utilisateur.
onPreExecute - exécuté avant doInBackground, a accès à l'interface utilisateur
onPostExecute - exécuté après doInBackground (ne fonctionne pas si AsyncTask a été annulé - à ce sujet dans les prochaines leçons), a accès à l'interface utilisateur.
Cette classe MyAsyncTask
class MyAsyncTask extends AsyncTask<Void, Void, Void> {
@Override
protected void onPreExecute() {
super.onPreExecute();
tvInfo.setText("Start");
}
@Override
protected Void doInBackground(Void... params) {
//your background method
return null;
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
tvInfo.setText("Finish");
}
}
Et voici comment appeler votre activité ou votre fragment
MyAsyncTask myAsyncTask = new MyAsyncTask ();
myAsyncTask.execute();
Exemple d'exemple AsyncTask avec progress
import Android.animation.ObjectAnimator;
import Android.os.AsyncTask;
import Android.support.v7.app.AppCompatActivity;
import Android.os.Bundle;
import Android.util.Log;
import Android.view.View;
import Android.view.animation.AccelerateDecelerateInterpolator;
import Android.view.animation.DecelerateInterpolator;
import Android.view.animation.LinearInterpolator;
import Android.widget.Button;
import Android.widget.ProgressBar;
import Android.widget.TextView;
public class AsyncTaskActivity extends AppCompatActivity implements View.OnClickListener {
Button btn;
ProgressBar progressBar;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.button1);
btn.setOnClickListener(this);
progressBar = (ProgressBar)findViewById(R.id.pbar);
}
public void onClick(View view) {
switch (view.getId()) {
case R.id.button1:
new LongOperation().execute("");
break;
}
}
private class LongOperation extends AsyncTask<String, Integer, String> {
@Override
protected String doInBackground(String... params) {
Log.d("AsyncTask", "doInBackground");
for (int i = 0; i < 5; i++) {
try {
Log.d("AsyncTask", "task "+(i + 1));
publishProgress(i + 1);
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.interrupted();
}
}
return "Completed";
}
@Override
protected void onPostExecute(String result) {
Log.d("AsyncTask", "onPostExecute");
TextView txt = (TextView) findViewById(R.id.output);
txt.setText(result);
progressBar.setProgress(0);
}
@Override
protected void onPreExecute() {
Log.d("AsyncTask", "onPreExecute");
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("onPreExecute");
progressBar.setMax(500);
progressBar.setProgress(0);
}
@Override
protected void onProgressUpdate(Integer... values) {
Log.d("AsyncTask", "onProgressUpdate "+values[0]);
TextView txt = (TextView) findViewById(R.id.output);
txt.setText("onProgressUpdate "+values[0]);
ObjectAnimator animation = ObjectAnimator.ofInt(progressBar, "progress", 100 * values[0]);
animation.setDuration(1000);
animation.setInterpolator(new LinearInterpolator());
animation.start();
}
}
}
Tâche asynchrone;
public class MainActivity extends AppCompatActivity {
private String ApiUrl="your_api";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyTask myTask=new MyTask();
try {
String result=myTask.execute(ApiUrl).get();
Toast.makeText(getApplicationContext(),result,Toast.LENGTH_SHORT).show();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public class MyTask extends AsyncTask<String,Void,String>{
@Override
protected String doInBackground(String... strings) {
String result="";
HttpURLConnection httpURLConnection=null;
URL url;
try {
url=new URL(strings[0]);
httpURLConnection=(HttpURLConnection) url.openConnection();
InputStream inputStream=httpURLConnection.getInputStream();
InputStreamReader reader=new InputStreamReader(inputStream);
result=getData(reader);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
public String getData(InputStreamReader reader) throws IOException{
String result="";
int data=reader.read();
while (data!=-1){
char now=(char) data;
result+=data;
data=reader.read();
}
return result;
}
}
}