I have a service that executes a huge time-consuming computation. So I added an AsyncTask
to run it in background. I have the call to requestLocationUpdates()
which apparently can't be executed in an AsyncTask without a Looper
. Most suggested against using a Looper
, for I don't know why. So finally I had to add a Runnable
in the AsyncTask.doInBackground()
with a Handler
. The Runnable
seems to be blocking the activity that calls this service. This does not happen when my application is minimised. In fact, another activity of my app is also momentarily blocked whenever the execution happens.
1. What exactly is happening when I call a Runnable on a Handler?
2. How do I make it really run in background?
private void forkAsyncForTracking(){
new AsyncTask<Void, Void, Void>(){
private Location loc = null;
@Override
protected Void doInBackground(Void... params) {
handler.post(new Runnable(){
@Override
public void run() {
loc = getLocation();//this blocks the activity
}
});
return null;
}
@Override
protected void onPostExecute(Void lol){
doIt(loc);
}
}.execute();
}
By default, a service runs on 'main' thread. So if you declare a handler as a private to the service, it's considered as declared on main thread. Hence, the runnable declared inside the doInBackground will execute on main thread. Remember, it depends on the handler which is posting the runnable on where it'll be executed. You've to declare the handler inside the worker thread (which in this case will be doInBackground method), and also define a looper using Looper.prepare() (since, by default a worker thread doesn't have a looper, so there'd be no message queue which the handler can use). Try this out, and that method shouldn't cause any blocking thereafter.
protected Void doInBackground(Void... params) {
Handler handler = new Handler(); //Declared on worker thread.
Looper.prepare();
handler.post(new Runnable(){
@Override
public void run() {
loc = getLocation();//this blocks the activity
}
});
return null;
}
Another approach could be to use an IntentService, which runs on a worker thread by default, so you won't need any async task then. For IntentService, check this out : http://developer.android.com/reference/android/app/IntentService.html