使用地理编码器根据纬度和经度检索地址会导致延迟。安卓
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,所以我相应地更改了您提供的代码中的参数。谢谢!它现在可以工作了。 很高兴我能帮上忙! :)以上是关于使用地理编码器根据纬度和经度检索地址会导致延迟。安卓的主要内容,如果未能解决你的问题,请参考以下文章
python中的地理编码使用API密钥从地址获取纬度和经度