Android中Firebase异步请求后无法更新GoogleMap信息窗口内容
问题解决:Google Map InfoWindow 首次加载不显示Firebase数据
问题原因
你的代码核心问题是异步请求的执行时机和InfoWindow的渲染机制不匹配:
- Firebase的
get()方法是异步执行的,getInfoWindow()会先返回布局View,此时异步请求还没完成,控件赋值时用的是静态变量的初始值(首次为null/默认内容)。 - 第二次点击Marker时,之前的异步请求已经完成,静态变量被赋值,所以能显示数据,但静态变量会被所有Marker共享,后续还会出现数据错乱的问题。
解决方案步骤
- 移除静态变量,改用局部变量或内部类持有数据,避免多Marker间的数据污染。
- 将控件赋值逻辑移到Firebase请求的
onComplete回调内部,确保数据加载完成后再更新控件。 - 数据加载完成后调用
marker.showInfoWindow()强制刷新InfoWindow,因为InfoWindow一旦渲染就不会自动更新。 - 增加异常处理,比如图片为null时设置默认占位图,避免崩溃。
修改后的完整代码
public class MyInfoWindowAdapter implements GoogleMap.InfoWindowAdapter { private final Context context; public MyInfoWindowAdapter(Context context) { this.context = context; } @Override public View getInfoWindow(@NonNull Marker marker) { if (!"Este es mi perfil".equals(marker.getTitle())) { // 加载自定义布局 View infoView = LayoutInflater.from(context).inflate(R.layout.custom_info, null); TextView titleMod = infoView.findViewById(R.id.title_mod); TextView snippMod = infoView.findViewById(R.id.snipp_mod); ImageView imagenMod = infoView.findViewById(R.id.imagen_mod); // 初始化显示加载占位符 snippMod.setText("加载中..."); imagenMod.setImageResource(R.drawable.default_profile); // 替换成你的默认图片 LatLng posicionMarker = marker.getPosition(); String idLocation = String.valueOf(posicionMarker.latitude).replace(".", "") + "_" + String.valueOf(posicionMarker.longitude).replace(".", ""); // 第一次请求获取chismesinfo数据 DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("chismesinfo"); databaseReference.child(idLocation).get().addOnCompleteListener(task -> { if (task.isSuccessful() && task.getResult() != null) { DataSnapshot snapshot = task.getResult(); String descripcion = snapshot.child("descripcion").getValue(String.class); String userId = snapshot.child("user").getValue(String.class); if (userId != null) { // 第二次请求获取用户数据 DatabaseReference usersReference = FirebaseDatabase.getInstance().getReference("users"); usersReference.child(userId).get().addOnCompleteListener(userTask -> { if (userTask.isSuccessful() && userTask.getResult() != null) { DataSnapshot userSnapshot = userTask.getResult(); String username = userSnapshot.child("name").getValue(String.class); String foto = userSnapshot.child("profile").getValue(String.class); // 更新控件内容 snippMod.setText(descripcion != null ? descripcion : "暂无描述"); titleMod.setText(username != null ? username : "匿名用户"); // 处理图片加载 if (foto != null) { try { byte[] imageAsByte = Base64.decode(foto, Base64.DEFAULT); Bitmap bitmap = BitmapFactory.decodeByteArray(imageAsByte, 0, imageAsByte.length); imagenMod.setImageBitmap(bitmap); } catch (IllegalArgumentException e) { imagenMod.setImageResource(R.drawable.default_profile); } } else { imagenMod.setImageResource(R.drawable.default_profile); } // 刷新InfoWindow,确保更新后的内容显示 marker.showInfoWindow(); } else { // 请求失败时显示默认内容 snippMod.setText("加载失败"); marker.showInfoWindow(); } }); } else { snippMod.setText("用户信息缺失"); marker.showInfoWindow(); } } else { snippMod.setText("加载失败"); marker.showInfoWindow(); } }); return infoView; } return null; } @Override public View getInfoContents(@NonNull Marker marker) { return null; } }
关键优化点说明
- 移除静态变量:所有数据变量改为局部变量,避免多Marker间的数据干扰。
- 异步回调内更新控件:确保只有当Firebase数据加载完成后,才更新控件内容。
- 强制刷新InfoWindow:调用
marker.showInfoWindow()触发重新渲染,让更新后的内容显示出来。 - 异常处理:增加图片解码异常、请求失败的处理逻辑,提升稳定性。
- 加载占位符:初始显示加载状态,提升用户体验。
内容的提问来源于stack exchange,提问作者Dp258
相关产品推荐
相关产品推荐

