onLocationChanged callback is made on what thread? The main UI thread?
Asked Answered
E

1

8

When this callback is made in my app, I have quite a bit work to do (reading & writing to SQL db through an ORM lib and a number of distance based calculations). Naturally I am concerned about not blocking the main UI thread so I've been trying (unsuccessfully) to find out if this is the thread on which the callback is made. If it is, I'm intending to do all the afore-mentioned work on an AsyncTask triggered when the callback is made. This same AsyncTask will receive events from 2 separate activity classes as well. (Responding to user input etc..)

A lot of the discussion I have found around this callback seems to be based around people trying to change the thread on which the callback is actually received. This makes no sense to me. Surely the platform determines the context of this callback and the sensible thing to do when it's received is offload any serious work onto another thread, for which AsyncTask seems appropriate.

If anyone can outline a successful pattern they've used here it would be really useful.

Extempore answered 21/6, 2012 at 0:13 Comment(0)
P
7

According to the Android reference documentation for LocationManager:

The calling thread must be a Looper thread such as the main thread of the calling Activity.

This means that the Thread that initializes the callback must be the main Thread or a Looper Thread.

I've found the best way to handle this is to register an OnLocationChanged receiver on the main Thread. Then, in my callback I'll create a Runnable to send to a background Thread where I'll perform any long-running tasks (like writing to the database).

ExecutorService mThreadPool = Executors.newSingleThreadExecutor();

@Override
public void onLocationChanged(Location location) {
    mThreadPool.execute(new Runnable() {
        @Override
        public void run() {
            // Perform your long-running tasks here.
            //...
        }
    });
}
Pikeman answered 21/6, 2012 at 0:29 Comment(2)
From the documentation it does seem that the thread on which onLocationChanged is called back on, depends on the parameters passed to whichever requestLocationUpdate(..) call is used. Also that if a Looper is not not one of the params then the callback will be made in the context of the main UI thread. Need to read a bit more about Loopers. The solution above looks sensible. I am now wondering how it compares with using an AsyncTask in terms of performance. So I will go and read the documentation as I should have done in the first place. Thanks for the help.Extempore
You're right, there are several options for registering a LocationListener callback. Reading the documentation is definitely recommended. The above solution is roughly equivalent to using an AsyncTask. I believe if you look at the source for the AsyncTask class you'll see that it uses an ExecutorService internally. However, if you don't need to interact with the UI Thread when your task has completed, you'll find the AsyncTask does more than you need.Pikeman

© 2022 - 2024 — McMap. All rights reserved.