Android Studio中两次异步请求后更新XML内TextView异常排查
解决Firebase异步请求导致Marker信息窗口首次加载无数据的问题
问题核心在于异步请求的执行顺序:你发起Firebase请求后立刻执行了UI设置代码,但此时Firebase还未返回数据,username、descripcion、foto都是初始默认值;第二次触发时,之前的addValueEventListener已缓存数据,回调执行后变量赋值完成,UI才正常显示。
修复方案
- 将UI更新逻辑移到第二次异步请求的
onDataChange回调内,确保两次数据都获取完成后再更新控件。 - 用
addListenerForSingleValueEvent替代addValueEventListener——你仅需单次获取数据,无需持续监听变化,避免不必要的回调触发和内存泄漏。
修改后的代码:
@Override public View getInfoWindow(@NonNull Marker marker) { if (!(marker.getTitle().toString().equals("Este es mi perfil"))) { View infoView = LayoutInflater.from(context).inflate(R.layout.custom_info, null); final TextView title_mod = infoView.findViewById(R.id.title_mod); final TextView snipp_mod = infoView.findViewById(R.id.snipp_mod); final ImageView imagen_mod = infoView.findViewById(R.id.imagen_mod); LatLng posicionMarker = marker.getPosition(); String idLocation = String.valueOf(posicionMarker.latitude).replace(".", "") + "_" + String.valueOf(posicionMarker.longitude).replace(".", ""); DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("chismesinfo"); databaseReference.child(idLocation).addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { if (snapshot.exists()) { String descripcion = snapshot.child("descripcion").getValue(String.class); String user = snapshot.child("user").getValue(String.class); DatabaseReference usersReference = FirebaseDatabase.getInstance().getReference("users"); usersReference.child(user).addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { if (snapshot.exists()) { String username = snapshot.child("name").getValue(String.class); String foto = snapshot.hasChild("profile") ? snapshot.child("profile").getValue(String.class) : null; // 所有数据就绪后更新UI title_mod.setText(username != null ? username : "未知用户"); snipp_mod.setText(descripcion != null ? descripcion : "无描述"); if (foto != null) { try { byte[] imageAsByte = Base64.decode(foto, Base64.DEFAULT); Bitmap bitmap = BitmapFactory.decodeByteArray(imageAsByte, 0, imageAsByte.length); imagen_mod.setImageBitmap(bitmap); } catch (IllegalArgumentException e) { imagen_mod.setImageResource(R.drawable.default_profile); } } else { imagen_mod.setImageResource(R.drawable.default_profile); } } else { title_mod.setText("未知用户"); snipp_mod.setText(descripcion != null ? descripcion : "无描述"); imagen_mod.setImageResource(R.drawable.default_profile); } } @Override public void onCancelled(@NonNull DatabaseError error) { title_mod.setText("加载失败"); snipp_mod.setText("加载失败"); } }); } else { title_mod.setText("未知位置"); snipp_mod.setText("无描述"); imagen_mod.setImageResource(R.drawable.default_profile); } } @Override public void onCancelled(@NonNull DatabaseError error) { title_mod.setText("加载失败"); snipp_mod.setText("加载失败"); } }); return infoView; } return super.getInfoWindow(marker); }
额外优化点
- 给控件设置默认资源(如
R.drawable.default_profile),避免加载失败时UI空白。 - 增加Base64解码异常捕获,提升代码鲁棒性。
- 变量改为局部变量,避免全局变量的线程安全问题。
- 处理
onCancelled回调,在请求失败时给出明确反馈。
内容的提问来源于stack exchange,提问作者Dp258
相关产品推荐
相关产品推荐

