Reputation: 6427
I have an app that needs to do an intensive database operation on start up. The app holds a local copy of the contacts on the phone and synchronizes with the android contact database on startup.
If a user starts the app, an Async Task is started that does the database synch in the background. If the user closes the app, the operation continues running which is fine. However if the user opens the app again, the Async Task is started and an error is produced.
Is there anyway of checking if the Task is already running from a different instance of the app?
Upvotes: 34
Views: 55247
Reputation: 71
I've managed to handle this problem with some sort of Singleton pattern. Hope it helps.
// 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) {
// ...
}
}
Upvotes: 7
Reputation: 2554
I think you should check the concept of Application
in Android
.
http://developer.android.com/reference/android/app/Application.html
In fact there is no such thing as
different instance of the app
. The Application
is always the same for all your Activities/Services.
That means that you'd left the Activity
and opened it again, 2 cases are possible:
AsyncTask
is dead already and it's safe to start a new oneApplication
was still alive, so AsyncTask
possibly still running.In 2nd case I will recommend to use some static variables, pointing to this AsyncTask
or it's state. If your app was still alive when 2nd time opened - all static references will be still valid, so you can successfully operate.
PS: By the way, in current approach be aware that your application can be terminated by the system at any time. So AsyncTask
can be interrupted in any moment. It it's not ok for you - please check IntentServices
- components, specially designed for background-operation purpose. http://developer.android.com/reference/android/app/IntentService.html
Good luck!
Upvotes: 3
Reputation: 72331
Use getStatus()
to get the status of your AsyncTask
. If status is AsyncTask.Status.RUNNING
then your task is running.
EDIT: you should reconsider your implementation and hold the AsyncTask
probably in a Service
or IntentService
to fetch your data from the web.
Upvotes: 97