使用地理编码器根据纬度和经度检索地址会导致延迟。安卓

Posted

技术标签:

【中文标题】使用地理编码器根据纬度和经度检索地址会导致延迟。安卓【英文标题】:Using Geocoder to retrieve address based on Latitude and Longitude causes lag. Android 【发布时间】:2016-11-20 15:15:24 【问题描述】:

我有一个地图活动,上面还有一个 EditText,我想在地图上有拖动时在该 EditText 中显示更改的地址。我目前正在使用 Geocoder 类根据地图提供的坐标检索地址。但是这种方式在地图的流畅拖动中造成了很大的延迟。有没有更好的方法来检索地址或更有效的方法来使用 Geocoder 类?现在,我已经在我的地图的 OnCameraChangeListener 事件中实现了 getAddress() 方法。这是代码。

mMap.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() 
            @Override
            public void onCameraChange(CameraPosition cameraPosition) 
                double latitude=mMap.getCameraPosition().target.latitude;
                double longitude=mMap.getCameraPosition().target.longitude;
                String _Location="";
                Geocoder geocoder = new Geocoder(getApplicationContext(), Locale.getDefault());
                try 
                    List<Address> listAddresses = geocoder.getFromLocation(latitude, longitude, 1);
                    if(null!=listAddresses&&listAddresses.size()>0)
                        _Location = listAddresses.get(0).getAddressLine(0);
                    
                 catch (IOException e) 
                    e.printStackTrace();
                
                EditText addressTxt=(EditText) findViewById(R.id.search_address_txt);
                addressTxt.setText(_Location);
            
        );

我看到另一个应用程序实现了,其中搜索的地址位于地图拖动的末尾,并且地图的运动没有滞后。

【问题讨论】:

【参考方案1】:

Geocoder$getFromLocation() 是一个阻塞调用,这意味着它将冻结 UI 线程,直到 api 返回地址。唯一的解决方案是在后台线程上运行此调用。

有两种方法可以实现:

    使用 Google 推荐的方式 - 使用 Intent Service。您可以找到有关如何here 的详细信息。就我个人而言,我觉得这太过分了,而且非常复杂。 使用AsyncTask。请参阅this 了解总体思路并根据您的需要实施。

另外,如果您使用的是 Rx,您可以从地理编码器中启动一个新的 observable,然后在不同的线程上观察并在主线程上订阅。

更新:我从我的一个旧项目中提取了这段代码,看看它是否有帮助。

AsyncGeocoderObject.java // object to pass to asynctask

public class AsyncGeocoderObject 

    public Location location; // location to get address from
    Geocoder geocoder; // the geocoder
    TextView textView; // textview to update text

    public AsyncGeocoderObject(Geocoder geocoder, Location location, TextView textView) 
        this.geocoder = geocoder;
        this.location = location;
        this.textView = textView;
    

AsyncTask 实现

public class AsyncGeocoder extends AsyncTask<AsyncGeocoderObject, Void, List<Address>> 

private TextView textView;

@Override
protected List<Address> doInBackground(AsyncGeocoderObject... asyncGeocoderObjects) 
    List<Address> addresses = null;
    AsyncGeocoderObject asyncGeocoderObject = asyncGeocoderObjects[0];
    textView = asyncGeocoderObject.textView;
    try 
        addresses = asyncGeocoderObject.geocoder.getFromLocation(asyncGeocoderObject.location.getLatitude(),
                asyncGeocoderObject.location.getLongitude(), 1);
     catch (IOException e) 
        e.printStackTrace();
    
    return addresses;


@Override
protected void onPostExecute(List<Address> addresses) 
    Log.v("onPostExecute", "location: " + addresses);
    String address;
    if (addresses != null)
        address = addresses.get(0).getLocality() + ", " + addresses.get(0).getCountryName();
    else address = "Service unavailable.";
    textView.setText(address);


位置改变时调用方法:

new AsyncGeocoder().execute(new AsyncGeocoderObject(
                new Geocoder(this),
                location,
                locationTV
        ));

希望这会有所帮助!

更新 2: 关于如何实现上述内容的说明:

    新建类AsyncGeocoderObject并复制内容 创建另一个类(可以是活动中的子类或不同的 java 文件中)AsyncGeocoder 并复制内容。

    现在,假设您想在MainActivity 中获取用户位置并在文本视图中显示地址,例如locationTV。实例化textview后,新建一个AsyncGeocoder的对象,并传入参数。例如:

    // in onCreate()
    new AsyncGeocoder().execute(new AsyncGeocoderObject(
            new Geocoder(this), // the geocoder object to get address
            location, // location object, 
            locationTV // the textview to set address on
    )); 
    

    另外,如果您没有位置对象,请使用您拥有的纬度和经度进行创建。 See this post for how to.

希望对您有所帮助!

【讨论】:

抱歉回复晚了。感谢帮助。但是你能指导我把代码放在哪里吗?在我需要获取地址的活动中?还是我要创建一个新的 java 类? @RehanYousaf 添加了更多细节。看看他们是否有帮助 我想使用 LatLng,所以我相应地更改了您提供的代码中的参数。谢谢!它现在可以工作了。 很高兴我能帮上忙! :)

以上是关于使用地理编码器根据纬度和经度检索地址会导致延迟。安卓的主要内容,如果未能解决你的问题,请参考以下文章

使用 iPhone 的纬度和经度进行反向地理编码

从地理编码纬度和经度获取地址

python中的地理编码使用API​​密钥从地址获取纬度和经度

从英国邮政编码地理编码经度和纬度? [复制]

有没有办法进行批量地理编码(通过地址获取纬度/经度,反之亦然)? [关闭]

使用地理编码器和 android Google Maps API v2 获取纬度和经度