是否有必要在单独的线程中查找获取位置?

发布于 2024-11-01 16:36:19 字数 4588 浏览 5 评论 0原文

我担心在主线程上查找位置信息(使用反向地理编码)会减慢我的用户界面。为了解决这个问题,我将信息放入 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]);
            } 
        }

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

仙女山的月亮 2024-11-08 16:36:19

我进行了一些快速搜索,没有看到任何对运行异步的 LocationManager 的具体引用,但我的假设是它确实如此或其调度方式不会影响 UI 性能,因为它是一项系统服务。

根据经验,我在主线程上获取位置并将其显示给用户没有任何问题。事实上,我计算了列表中大约 100 个项目的距离,UI 没有明显变慢。不过,我认为后一个计算应该考虑 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
线程,例如主线程
调用活动。

http://developer.android.com/reference/android/os/Looper.html 基本上,

当您的 LocationAsyncTask 完成执行时,它就消失了,因此事件回调发生在不再存在的线程上。 Looper 将启动一个消息循环来接受这些 LocationManager 事件。

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.

巴黎夜雨 2024-11-08 16:36:19

iOS SDK 的核心位置提供了一个 CLLocationManager 对象,其中包含名为 startUpdatingLocationstartMonitoringSignificantLocationChanges 的实例方法,这两个方法都是异步工作的。调用其中之一后,您只需实现回调 locationManager:didUpdateToLocation:fromLocation 来处理位置更新。我敢打赌 Android 也会做类似的事情。如果没有,请提交错误。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文