Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android AsyncTask - avoid multiple instances running

Tags:

android

I have AsyncTask that processes some background HTTP stuff. AsyncTask runs on schedule (Alarms/service) and sometime user executes it manually.

I process records from SQLite and I noticed double-posts on server which tells me that sometime scheduled task runs and at the same time user runs it manually causing same record to be read and processed from DB twice. I remove records after they processed but still get this.

How should I handle it ? Maybe organize some kind of queing?

like image 686
katit Avatar asked Jul 11 '11 02:07

katit


People also ask

How many times an instance of AsyncTask can be executed?

AsyncTask instances can only be used one time.

What are the problems in AsyncTask?

In summary, the three most common issues with AsyncTask are: Memory leaks. Cancellation of background work. Computational cost.

What happens to AsyncTask if activity is destroyed?

If you start an AsyncTask inside an Activity and you rotate the device, the Activity will be destroyed and a new instance will be created. But the AsyncTask will not die. It will go on living until it completes.

Is it possible to start AsyncTask from background thread?

To start an AsyncTask the following snippet must be present in the MainActivity class : MyTask myTask = new MyTask(); myTask. execute(); In the above snippet we've used a sample classname that extends AsyncTask and execute method is used to start the background thread.


3 Answers

You can execute your AsyncTask's on an Executor using executeOnExecutor()

To make sure that the threads are running in a serial fashion please use: SERIAL_EXECUTOR.

Misc: How to use an Executor

If several activities are accessing your DB why don't create a sort of gateway database helper and use the synchronized block to ensure only one thread has access to it at an instant

like image 107
Reno Avatar answered Oct 22 '22 03:10

Reno


Or, you can try this to see if the Task is currently running or not:

if (katitsAsyncTask.getStatus().equals(AsyncTask.Status.FINISHED))
     katitsAsyncTask.execute();
else
     // wait until it's done.
like image 11
BonanzaDriver Avatar answered Oct 22 '22 03:10

BonanzaDriver


Initialize the AsyncTask to null. Only create a new one if it is null. In onPostExecute, set it to null again, at the end. Do the same in onCancelled, in case the user cancels this. Here's some untested code to illustrate the basic idea.

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class FooActivity extends Activity {

    private class MyAsyncTask extends AsyncTask<Foo, Foo, Foo> {
        @Override
        protected void onPostExecute(Foo foo) {
                    // do stuff
            mMyAsyncTask = null;
        }

        @Override
        protected void onCancelled() {
            // TODO Auto-generated method stub
            mMyAsyncTask = null;
        }

        @Override
        protected Foo doInBackground(Foo... params) {
                    try {
                         // dangerous stuff                         
                    } catch (Exception e) {
                        // handle. Now we know we'll hit onPostExecute()
                    }

            return null;
        }
    }

    private MyAsyncTask mMyAsyncTask = null;

    @Override
    public void onCreate(Bundle bundle) {
        Button button = (Button) findViewById(R.id.b2);
        button.setOnClickListener(new View.OnClickListener() {

            public void onClick(View v) {
                if (mMyAsyncTask == null) {
                    mMyAsyncTask = new MyAsyncTask();
                    mMyAsyncTask.execute(null);
                }
            }

        });
    }

}

like image 6
Thomas Dignan Avatar answered Oct 22 '22 02:10

Thomas Dignan