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

Java 使用地理编码器根据纬度和经度检索地址会导致延迟。安卓,java,android,google-maps,google-maps-api-3,Java,Android,Google Maps,Google Maps Api 3,我有一个地图活动,上面还有一个EditText,每当地图上有拖动时,我想在EditText中显示不断变化的地址。我目前正在使用Geocoder类根据地图提供的坐标检索地址。但这种方式会导致地图的流畅拖动运动出现很大的滞后。有没有更好的方法来检索地址,或者有没有更有效的方法来使用Geocoder类?现在,我已经在映射的OnCameraChangeListener事件中实现了getAddress()方法。这是代码 mMap.setOnCameraChangeListener(new GoogleMa

我有一个地图活动,上面还有一个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);
            }
        });
mMap.setOnCameraChangeListener(新GoogleMap.OnCameraChangeListener(){
@凌驾
CameraChange上的公共无效(CameraPosition CameraPosition){
double latitude=mMap.getCameraPosition().target.latitude;
double longitude=mMap.getCameraPosition().target.longitude;
字符串_Location=“”;
Geocoder Geocoder=新的Geocoder(getApplicationContext(),Locale.getDefault());
试一试{
List listAddresses=geocoder.getFromLocation(纬度、经度,1);
if(null!=listAddresses&&listAddresses.size()>0){
_位置=listAddresses.get(0).getAddressLine(0);
}
}捕获(IOE异常){
e、 printStackTrace();
}
EditText addressTxt=(EditText)findViewById(R.id.search\u address\u txt);
addressTxt.setText(_位置);
}
});

我见过另一个应用程序实现,其中搜索的地址位于地图拖动的末尾,并且地图的运动没有延迟

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

有两种方法可以实现这一点:

  • 使用谷歌推荐的方式-使用
    意向服务
    。您可以找到有关如何操作的详细信息。就我个人而言,我觉得这太过分了,而且非常复杂
  • 使用
    异步任务
    。查看以获得总体思路,并根据需要实施
  • 此外,如果您正在使用Rx,您可以从地理编码器启动一个新的observable,在不同的线程上进行观察,并在主线程上订阅

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


    异步任务实现

    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);
    }
    }
    
    希望这有帮助

    更新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
    )); 
    
    此外,如果没有位置对象,请使用现有的纬度和经度创建


  • 希望这对你有帮助

    很抱歉迟了答复。谢谢你的帮助。但是你能告诉我该把代码放在哪里吗?在我需要获得地址的活动中?还是我要创建一个新的java类?@Rehanhousaf添加了更多细节。看看它们是否有用我想使用LatLng,所以我相应地更改了您提供的代码中的参数。非常感谢。现在开始工作了。很高兴我能帮忙!:)
    new AsyncGeocoder().execute(new AsyncGeocoderObject(
                    new Geocoder(this),
                    location,
                    locationTV
            ));
    
    // 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
    ));