Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Async task does not work properly (doInBackground not executing) when service runs in background, Android

I noticed that sometimes Async task does not work properly , Actually its doInBackground() method does not get called , this happens mostly when any service run in background for that activity. For Example , when music runs in background with service, the Async task does not parse XML in background as its doInBackground does not work that time and the progress Dialog or progressBar kept spinning.

I read in few articles that AsyncTask.THREAD_POOL_EXECUTOR can help in these issues like :

if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ) {
    new Test().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else {
    new Test().execute();
}

but that did not help in my case. Having the same issue after the above implmentation.

Here I am giving just a bit of my sample code to understand what I am doing::

public class TestAct extends Activity {

    ImageButton play,forward,backward;  
    private ListView mList;
    // many more variables

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test_layout);

        //binding the service here
        // start service is called

        init();
    }

    private void init(){

        play=(ImageButton)findViewById(R.id.playBtn);
        forward=(ImageButton)findViewById(R.id.forward);
        backward=(ImageButton)findViewById(R.id.backward);  
        mList=(ListView)findViewById(R.id.list);

        new GetData().execute();

        play.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // calling the play() method of ServiceConnection here
            }
        });

            // adding header to Listview
            // other code and click listeners

    }

    class GetData extends AsyncTask<Void, Void, Void>{

        @Override
        protected void onPreExecute() {
            super.onPreExecute();

            // starting the progress Bar
            // initializing the Arraylist,Maps etc
        }

        @Override
        protected Void doInBackground(Void... params) {
            //parsing the XML here
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);

            // stop the ProgressBar 
            // Updating my UI here
                    // setting Adapter for ListView 
        }   
    }
}

This works fine generally but hangs when Service runs in backgound (I mean when music is playing in back).

I am not getting the exact reason behind this problem of Async task. Will mannual thread implementation help in this case ...??

Well, I think the problem is because "Service runs in main thread so when it runs, it blocks my AsyncTask to run"... So I think If we can run Service in background thread then that can help . Thats why I tried IntentService for running service in separate thread but I am in doubt... if IntentService can run for indefinite time similar to Service ... and Also IntentService blocks AsyncTask few times. So I dont't think its 100% perfect solutions for this kind of problem.

Can anyone help me to sort out this problem and understand the complete scenario.

Thanks in advance.

like image 314
Dinesh Sharma Avatar asked Feb 15 '13 09:02

Dinesh Sharma


2 Answers

Sometimes you will want more control over your service's lifecycle than what IntentService gives you, in those cases you can just create a thread in the service and run your background code in that. Actually, to be more specific, create a HandlerThread which includes a Looper so you can use the standard android method for communication (messages) between your main thread and the background thread.

Answered here

like image 169
Aashish Bhatnagar Avatar answered Oct 11 '22 23:10

Aashish Bhatnagar


I think the problem is starting another GetData AsyncTask before the previous one has been finished. Before executing another task make sure that previous one is complete. To do this use following code:

// make sure we don't collide with another pending AsyncTask
if (getDataTask == null || getDataTask.getStatus() == AsyncTask.Status.FINISHED || getDataTask.isCancelled()) {
    getDataTask= new GetData();
    getDataTask.execute();
} 

Also make sure that you have a reference for running tasks. You can use subclass of Application class for doing this while your application is running or override onSaveInstanceState(Bundle outState) and receive a reference to it in onCreate(Bundle savedInstanceState).

like image 40
bohlool.mohammadi Avatar answered Oct 11 '22 22:10

bohlool.mohammadi