Android API 33中Geocoder.getFromLocation弃用,求替代方案
解决API 33中Geocoder.getFromLocation()弃用问题
原同步方法geocoder.getFromLocation()会阻塞主线程导致UI卡顿,Android在API 33推出了异步版本getFromLocation(double, double, int, GeocodeListener)替代它。因为是异步操作,无法直接返回结果,需要用回调传递数据,以下是适配后的完整实现:
1. 定义回调接口
用来传递城市名称的获取结果:
// 定义回调接口,处理城市名称获取结果 interface OnCityNameResultListener { void onCityNameFound(String cityName); // 找到城市时触发 void onCityNameNotFound(); // 未找到或出错时触发 }
2. 适配API 33的异步方法
兼容新旧版本的实现逻辑:
public void getCityName(double longitude, double latitude, OnCityNameResultListener listener) { Geocoder geocoder = new Geocoder(getActivity().getApplicationContext(), Locale.getDefault()); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { // API 33及以上用异步方法 geocoder.getFromLocation(latitude, longitude, 3, new Geocoder.GeocodeListener() { @Override public void onGeocode(List<Address> addresses) { String cityName = "Not Found"; boolean cityFound = false; for (Address adr : addresses) { if (adr != null) { String city = adr.getLocality(); if (city != null && !city.isEmpty()) { cityName = city; cityFound = true; break; // 找到第一个有效城市就停止遍历 } } } if (cityFound) { listener.onCityNameFound(cityName); } else { Log.d("TAG", "CITY NOT FOUND"); Toast.makeText(getActivity().getApplicationContext(), "USER CITY NOT FOUND...", Toast.LENGTH_SHORT).show(); listener.onCityNameNotFound(); } } @Override public void onError(String errorMessage) { Log.e("Geocoder", "Error: " + errorMessage); Toast.makeText(getActivity().getApplicationContext(), "获取城市失败", Toast.LENGTH_SHORT).show(); listener.onCityNameNotFound(); } }); } else { // API 33以下用原同步逻辑,保持兼容性 try { List<Address> addresses = geocoder.getFromLocation(latitude, longitude, 3); String cityName = "Not Found"; boolean cityFound = false; for (Address adr : addresses) { if (adr != null) { String city = adr.getLocality(); if (city != null && !city.isEmpty()) { cityName = city; cityFound = true; break; } } } if (cityFound) { listener.onCityNameFound(cityName); } else { Log.d("TAG", "CITY NOT FOUND"); Toast.makeText(getActivity().getApplicationContext(), "USER CITY NOT FOUND...", Toast.LENGTH_SHORT).show(); listener.onCityNameNotFound(); } } catch (IOException e) { e.printStackTrace(); Log.e("Geocoder", "IOException: " + e.getMessage()); Toast.makeText(getActivity().getApplicationContext(), "获取城市失败", Toast.LENGTH_SHORT).show(); listener.onCityNameNotFound(); } } }
3. 调用示例
在需要获取城市名称的地方调用方法,通过回调处理结果:
// 传入经纬度和回调实现 getCityName(longitude, latitude, new OnCityNameResultListener() { @Override public void onCityNameFound(String cityName) { // 这里处理获取到的城市,比如更新UI Log.d("TAG", "找到城市: " + cityName); // textView.setText(cityName); } @Override public void onCityNameNotFound() { // 处理未找到城市的逻辑 } });
注意事项
- 异步方法不会阻塞主线程,可安全在UI线程调用,回调方法也运行在调用线程,直接更新UI无需额外切换线程。
- 若Geocoder需要联网获取数据,记得在Manifest中添加权限:
<uses-permission android:name="android.permission.INTERNET" />
内容的提问来源于stack exchange,提问作者Belleren
相关产品推荐
相关产品推荐

