J'ai une application qui doit effectuer une opération de base de données intensive au démarrage. L'application contient une copie locale des contacts sur le téléphone et se synchronise avec la base de données de contacts Android au démarrage.
Si un utilisateur démarre l'application, une tâche asynchrone est lancée pour effectuer la synchronisation de la base de données en arrière-plan. Si l'utilisateur ferme l'application, l'opération continue de fonctionner, ce qui est correct. Cependant, si l'utilisateur ouvre à nouveau l'application, la tâche asynchrone démarre et une erreur se produit.
Est-il possible de vérifier si la tâche est déjà en cours d'exécution à partir d'une autre instance de l'application?
Je pense que vous devriez vérifier le concept de Application
dans Android
. http://developer.Android.com/reference/Android/app/Application.html
En fait, il n’existe pas de
instance différente de l'application
. Le Application
est toujours le même pour tous vos Activities/Services.
Cela signifie que vous avez quitté le Activity
et l'avez rouvert, 2 cas sont possibles:
AsyncTask
est déjà mort et il est sûr d'en démarrer un nouveauApplication
était toujours en vie, donc AsyncTask
peut-être encore en cours d'exécution.Dans le deuxième cas, je recommanderai d'utiliser certaines variables statiques, pointant vers ce AsyncTask
ou son état. Si votre application était encore en vie lors de la 2e ouverture - toutes les références statiques seront toujours valides, afin que vous puissiez fonctionner correctement.
PS: Au fait, dans l'approche actuelle, sachez que votre application peut être résiliée par le système à tout moment. Ainsi, AsyncTask
peut être interrompu à tout moment. Ce n'est pas bien pour vous - veuillez vérifier IntentServices
- composants, spécialement conçus pour le fonctionnement en arrière-plan. http://developer.Android.com/reference/Android/app/IntentService.html
Bonne chance!
Utilisez getStatus()
pour obtenir l'état de votre AsyncTask
. Si le statut est AsyncTask.Status.RUNNING
alors votre tâche est en cours d'exécution.
ÉDITER: vous devriez reconsidérer votre implémentation et maintenir le AsyncTask
probablement dans un Service
ou IntentService
pour récupérer vos données sur le web.
Oui, les gars, voici quelques exemples.
LoadMusicInBackground lmib = new LoadMusicInBackground();
if(lmib.getStatus() == AsyncTask.Status.PENDING){
// My AsyncTask has not started yet
}
if(lmib.getStatus() == AsyncTask.Status.RUNNING){
// My AsyncTask is currently doing work in doInBackground()
}
if(lmib.getStatus() == AsyncTask.Status.FINISHED){
// My AsyncTask is done and onPostExecute was called
}
J'ai réussi à gérer ce problème avec une sorte de motif Singleton. J'espère que cela aide.
// fill the places database from a JSON object
public class myAsyncTask extends AsyncTask<Void,Integer,Integer> {
Activity mContext = null;
static AsyncTask<Void,Integer,Integer> myAsyncTaskInstance = null;
// Private Constructor: can't be called from outside this class
private myAsyncTask(Activity iContext) {
mContext = iContext;
}
public static AsyncTask<Void, Integer, Integer> getInstance(Activity iContext) {
// if the current async task is already running, return null: no new async task
// shall be created if an instance is already running
if (myAsyncTaskInstance != null && myAsyncTaskInstance.getStatus() == Status.RUNNING) {
// it can be running but cancelled, in that case, return a new instance
if (myAsyncTaskInstance.isCancelled()) {
myAsyncTaskInstance = new myAsyncTask(iContext);
} else {
// display a toast to say "try later"
Toast.makeText(iContext, "A task is already running, try later", Toast.LENGTH_SHORT).show();
return null;
}
}
//if the current async task is pending, it can be executed return this instance
if (myAsyncTaskInstance != null && myAsyncTaskInstance.getStatus() == Status.PENDING) {
return myAsyncTaskInstance;
}
//if the current async task is finished, it can't be executed another time, so return a new instance
if (myAsyncTaskInstance != null && myAsyncTaskInstance.getStatus() == Status.FINISHED) {
myAsyncTaskInstance = new myAsyncTask(iContext);
}
// if the current async task is null, create a new instance
if (myAsyncTaskInstance == null) {
myAsyncTaskInstance = new myAsyncTask(iContext);
}
// return the current instance
return myAsyncTaskInstance;
}
@Override
protected Integer doInBackground(Void... iUnUsed) {
// ...
}
}