开发者

Is it necessary to find get locations in a separate thread?

I was worried that finding location info (with reverse geocoding) on the main thread would slow up my UI. To solve this problem I put the info into a AsyncTask (code b开发者_StackOverflow社区elow) Now I want to add location listeners, I am having all sorts of problems.

Ive done a bit of research and now wonder... Is it even necessary to put location code in an AsyncTask? Maybe Android just "naturally" finds location info asynchronously?

  public class LocationAsyncTask extends AsyncTask<Void, String, String> {





        @Override  protected void onPostExecute(String result) {
            // TODO Auto-generated method stub   
            tvLocation.setText(result);

            }  

        @Override  
        protected void onPreExecute() {
            // TODO Auto-generated method stub   
            tvLocation.setText("Finding current location");

            } 


        @Override  
        protected String doInBackground(Void... params) {  
            // TODO Auto-generated method stub 
            LocationManager locationManager;
            String context = Context.LOCATION_SERVICE;
            locationManager = (LocationManager)getSystemService(context);

            Criteria criteria = new Criteria();
            criteria.setAccuracy(Criteria.ACCURACY_FINE);
            criteria.setAltitudeRequired(false);
            criteria.setBearingRequired(false);
            criteria.setCostAllowed(true);
            criteria.setPowerRequirement(Criteria.POWER_LOW);

            String provider = locationManager.getBestProvider(criteria, true);
            Location location =locationManager.getLastKnownLocation(provider);
            String strUpdateResult = updateWithANewLocation(location);

        //locationManager.requestLocationUpdates(provider, 1000, 10, locationListener);


            return strUpdateResult; 
            }  

        private String updateWithANewLocation(Location location) {
            // TODO Auto-generated method stub
            StringBuilder sbLocation = new StringBuilder();
            String strLocation = new String();
            TextView myLocationText;

            String addressString = "No address found";
            String latLongString = "";

                //If there is a location
                if (location!= null) {

                        double latitude = location.getLatitude();
                        double longitude = location.getLongitude();
                        double altitude = location.getAltitude();
                        float accuracy = location.getAccuracy();
                        float bearing = location.getBearing();
                        long time = location.getTime();
                        float speed = location.getSpeed();
                        String prov = location.getProvider();
                        strLocation = "Latitude: " + latitude + "\nLongitude: " +  longitude + "\n" ;
                        publishProgress(strLocation);

                        Geocoder gc = new Geocoder(LateRunner.this, Locale.getDefault());
                        try {
                            List<Address> addresses = gc.getFromLocation(latitude, longitude, 1);

                            //if location and then address is found
                            if (addresses.size() > 0 ) {
                                Address address = addresses.get(0);

                                for (int i=0; i <address.getMaxAddressLineIndex(); i++) {
                                    sbLocation.append(address.getAddressLine(i)).append("\n");
                                }
                                strLocation= sbLocation.toString();
                                publishProgress(strLocation);
                            }
                            //if location but no address
                            else {
                                strLocation = "Latitude: " + latitude + "\nLongitude: " +  longitude + "\n";    
                                publishProgress(strLocation);
                            } //end try

                        } catch (IOException e) {
                            strLocation = "Latitude: " + latitude + "\nLongitude: " +  longitude + "\n";    
                            publishProgress(strLocation);

                        }//end catch
                    }

                //If no location found
                else {
                    strLocation = "Unable to find location. ";
                    publishProgress(strLocation);
                }
                return strLocation;



        }// end updateWithANewLocation()






        @Override  protected void onProgressUpdate(String... result) { 
            // TODO Auto-generated method stub 
            tvLocation.setText(result[0]);
            } 
        }


I did some quick searching and didn't see any specific references to the LocationManager running async, but my assumption is that it does or its scheduled in a way that doesn't impact UI performance since it's a system service.

From experience I have had no issue getting the location on the main thread and displaying it back to the user. In fact I calculate the distance away for about 100 items in a list without a noticeable slowdown on the UI. The latter calc though is where I'd say you should think about AsyncTask, since it can easily impact performance. Though also be careful of how long your AsyncTask tasks and the update interval of the LocationManager location updates.

Depending on how long each call to updateWithANewLocation takes you might want to think about putting that on a background task and leave the LocationManager on the Main thread.

I'm assuming where you're having an issue is with the event handling on the LocationManager. The following should give some insight into that part of the issue:

http://developer.android.com/reference/android/location/LocationManager.html#requestLocationUpdates%28java.lang.String,%20long,%20float,%20android.location.LocationListener%29

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

http://developer.android.com/reference/android/os/Looper.html

Basically when your LocationAsyncTask finished executing, its gone, so the event callbacks are happening to a thread that doesn't exist anymore. The Looper would initiate a message loop to accept those LocationManager events.


Core Location of the iOS SDK provides a CLLocationManager object with instance methods called startUpdatingLocation and startMonitoringSignificantLocationChanges that both work asynchronously. After calling one of those, you just implement the callback locationManager:didUpdateToLocation:fromLocation to handle the location updates. I bet Android does something similar. If not, file a bug.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜