地图显示用户位置失败:GoogleApiClient未连接异常求助
问题分析与修复方案
核心问题拆解
你遇到的java.lang.IllegalStateException: GoogleApiClient is not connected yet异常,本质是异步操作的时机错误:apiClient.connect()是异步执行的,不会立刻完成连接,但你直接在调用connect()后就执行requestLocationUpdates,此时客户端还处于未连接状态。而地图不显示位置,大概率是因为displayLocation的调用时机不对,或者Marker的更新逻辑存在漏洞。
分步修复代码
1. 修正GoogleApiClient连接逻辑,将位置请求移到回调中
首先修改startLocationListener,只负责初始化和触发连接,不要直接请求位置更新:
public void startLocationListener() { if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, AppConstants.LOC_PERM_CODE); } else { if (apiClient == null) { initAPIClient(); } if (!apiClient.isConnected()) { apiClient.connect(); } // 移除这里的requestLocationUpdates,移到onConnected回调中 } }
然后在onConnected回调中执行位置请求和初始位置显示(这才是客户端确认连接成功的正确时机):
@Override public void onConnected(@Nullable Bundle bundle) { if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { // 开始请求位置更新 LocationServices.FusedLocationApi.requestLocationUpdates(apiClient, locationRequest, this); // 获取最后已知位置并显示 mLastLocation = LocationServices.FusedLocationApi.getLastLocation(apiClient); if (mLastLocation != null) { displayLocation(); } } }
2. 完善displayLocation方法,确保地图Marker正确更新
确保在拿到位置后,正确创建或更新地图上的Marker,同时移动地图到当前位置:
private void displayLocation() { // 先判断地图和位置是否初始化完成 if (mGmap == null || mLastLocation == null) { return; } latitude = mLastLocation.getLatitude(); longitude = mLastLocation.getLongitude(); // 更新Marker:如果已有则移除,再创建新的 if (currentMarker != null) { currentMarker.remove(); } LatLng currentLatLng = new LatLng(latitude, longitude); MarkerOptions markerOptions = new MarkerOptions() .position(currentLatLng) .title("Your Current Location") .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE)); currentMarker = mGmap.addMarker(markerOptions); // 移动地图到当前位置,缩放级别设为15(适合街景级显示) mGmap.moveCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 15)); }
3. 完善位置更新回调与停止监听逻辑
在onLocationChanged中更新位置并刷新地图:
@Override public void onLocationChanged(Location location) { mLastLocation = location; displayLocation(); // 位置变化时实时更新地图显示 }
修正stopLocationListener,确保正确移除更新并断开客户端:
public void stopLocationListener() { if (apiClient != null && apiClient.isConnected()) { LocationServices.FusedLocationApi.removeLocationUpdates(apiClient, this); apiClient.disconnect(); } if (currentMarker != null) { currentMarker.remove(); currentMarker = null; } }
4. 补充连接异常处理
完善onConnectionSuspended和onConnectionFailed,提升鲁棒性:
@Override public void onConnectionSuspended(int i) { apiClient.connect(); // 连接断开后尝试重新连接 } @Override public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { Snackbar.make(getActivity().findViewById(android.R.id.content), "GoogleApiClient连接失败: " + connectionResult.getErrorMessage(), Snackbar.LENGTH_LONG).show(); }
5. 修正setUpLocation初始化逻辑
确保权限、Play服务检查后,正确初始化位置请求和客户端:
private void setUpLocation() { if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}, AppConstants.LOC_PERM_CODE); return; } if (checkPlayServices()) { makeLocationRequest(); initAPIClient(); if (statusSwitch.isChecked()) { apiClient.connect(); } } else { Snackbar.make(getActivity().findViewById(android.R.id.content), "你的设备不支持Google Play服务", Snackbar.LENGTH_LONG).show(); } }
关键修复要点总结
- 永远不要在
apiClient.connect()后立刻调用位置相关API,必须等待onConnected回调确认连接成功。 - 确保
displayLocation只在mGmap和mLastLocation都初始化完成后执行。 - 位置变化时,通过
onLocationChanged实时更新地图Marker。 - 停止监听时,必须移除位置更新并断开GoogleApiClient,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Andromeda
相关产品推荐
相关产品推荐

