Нужно ли искать местоположения в отдельной теме? - PullRequest
2 голосов
/ 17 апреля 2011

Я беспокоился, что поиск информации о местоположении (с обратным геокодированием) в главном потоке замедлит мой пользовательский интерфейс.Чтобы решить эту проблему, я поместил информацию в AsyncTask (код ниже). Теперь я хочу добавить слушателей местоположения, у меня возникают всевозможные проблемы.

Я провел небольшое исследование и теперь удивляюсь ... Нужно ли даже помещать код местоположения в AsyncTask?Может быть, Android просто «естественно» находит информацию о местоположении асинхронно?

  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]);
            } 
        }

Ответы [ 2 ]

3 голосов
/ 17 апреля 2011

Я провел быстрый поиск и не увидел каких-либо конкретных ссылок на LocationManager, выполняющий асинхронный вызов, но я предполагаю, что это происходит или он запланирован таким образом, что это не влияет на производительность пользовательского интерфейса, поскольку это системная служба.

Из опыта у меня не было проблем с получением местоположения в главном потоке и отображением его обратно пользователю.Фактически я вычисляю расстояние около 100 элементов в списке без заметного замедления пользовательского интерфейса.В последнем калькуляторе я бы сказал, что вам следует подумать об AsyncTask, поскольку он может легко повлиять на производительность.Хотя также будьте осторожны с тем, как долго ваши задачи AsyncTask и интервал обновления обновлений местоположения LocationManager.

В зависимости от того, сколько времени занимает каждый вызов updateWithANewLocation, вы можете подумать о том, чтобы поместить это в фоновую задачу и оставить LocationManager в главном потоке.

Я предполагаю, что у вас возникла проблема с обработкой событий в LocationManager.Следующее должно дать некоторое представление об этой части проблемы:

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

Вызывающий поток должен быть потоком Looper, таким как основной поток вызывающего Activity.

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

По существу, когда ваш LocationAsyncTask завершил выполнение, он ушел, поэтому обратные вызовы событий происходят с потоком, который больше не существует.Looper инициирует цикл обработки сообщений, чтобы принять эти события LocationManager.

0 голосов
/ 17 апреля 2011

Базовое расположение iOS SDK предоставляет объект CLLocationManager с экземплярами методов, называемыми startUpdatingLocation и startMonitoringSignificantLocationChanges, которые работают асинхронно. После вызова одного из них вы просто реализуете обратный вызов locationManager:didUpdateToLocation:fromLocation для обработки обновлений местоположения. Бьюсь об заклад, Android делает нечто подобное. Если нет, сообщите об ошибке.

...