You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Google Map自定义Marker仅显示一个的技术求助

解决Google Map自定义Marker仅显示一个的问题

我仔细看了你的代码,发现问题主要出在全局复用同一个View生成Marker图标上,还有一些循环逻辑可以优化,下面给你一步步拆解和修复:

问题根源

  1. 全局View导致Bitmap复用冲突:你定义了全局的View child,只在初始化时inflate了一次布局。每次调用getMarkerImage时,都是修改同一个View的文本然后生成Bitmap——这会导致所有Marker的Icon最终都指向最后一次生成的Bitmap对象,前面的Marker图标会被后续的绘制覆盖,自然就只能看到最后一个Marker的自定义图标了。
  2. 嵌套循环逻辑冗余:在onDataChange里,你先遍历用户快照,再嵌套遍历UIDLocation的所有条目,不仅效率低,还可能导致同一个Marker被重复修改,出现不必要的逻辑混乱。

修复方案

1. 每次生成图标时创建独立的View实例

把View child的初始化移到getMarkerImage方法内部,每次调用都inflate一个全新的View,这样每个Marker的图标都是基于独立的View生成,不会互相干扰。

2. 优化循环逻辑,减少不必要的遍历

先把符合条件的用户key和数据存到集合里,再直接遍历已有的Marker集合,根据key判断是否需要显示并设置图标,这样比嵌套循环高效得多。

修改后的完整代码

geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
    @Override
    public void onKeyEntered(String key, GeoLocation location) {
        UIDLocation.put(key,location);
        Marker marker = mMap.addMarker(new MarkerOptions()
                .position(new LatLng(location.latitude, location.longitude))
                .title(key));
        markers.put(key, marker);
    }
});

// MarkeringMap is called when someone click on card which contains the category names
public void MarkeringMap(String string){
    Query query = FirebaseDatabase.getInstance().getReference().child("WorkMen")
            .orderByChild("subcategory")
            .startAt(string)
            .endAt(string + "\uf8ff")
            .limitToLast(50);
    query.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            if(dataSnapshot.exists()) {
                Toast.makeText(getActivity(),"there is something",Toast.LENGTH_SHORT).show();
            }
            // 先把符合条件的用户key和数据存到集合中
            Set<String> validUserKeys = new HashSet<>();
            Map<String, Users> validUsersMap = new HashMap<>();
            usersLists.clear(); // 清空旧数据避免重复
            for (DataSnapshot usersnapshot : dataSnapshot.getChildren()) {
                Users users = usersnapshot.getValue(Users.class);
                usersLists.add(users);
                Toast.makeText(getActivity(),users.getName()+"this is username ",Toast.LENGTH_SHORT).show();
                String keystring = usersnapshot.getKey();
                validUserKeys.add(keystring);
                validUsersMap.put(keystring, users);
            }

            // 遍历所有Marker,统一更新显示状态和图标
            for (Map.Entry<String, Marker> entry : markers.entrySet()) {
                Marker marker = entry.getValue();
                String key = entry.getKey();
                if (validUserKeys.contains(key)) {
                    // 显示符合条件的Marker并设置自定义图标
                    marker.setVisible(true);
                    Users user = validUsersMap.get(key);
                    Bitmap b = getMarkerImage(user.getName());
                    marker.setIcon(BitmapDescriptorFactory.fromBitmap(b));
                } else {
                    // 隐藏不符合条件的Marker
                    marker.setVisible(false);
                }
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            // 处理查询取消的异常,方便调试
            Log.e("FirebaseQuery", "Query cancelled", databaseError.toException());
        }
    });
}

public Bitmap getMarkerImage(String name){
    // 每次调用都实例化新的View,彻底避免复用冲突
    View child = getLayoutInflater().inflate(R.layout.category_tags_items, null);
    TextView textView1 = (TextView)child.findViewById(R.id.tag_Category_name);
    textView1.setText(name);
    // Drawable myDrawable = getResources().getDrawable(R.drawable.default_avatar); // 保留你的自定义Drawable设置

    // 正确测量View并生成Bitmap
    child.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
            View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
    child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());
    child.buildDrawingCache();
    Bitmap bitmap = Bitmap.createBitmap(child.getMeasuredWidth(), child.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    canvas.drawColor(Color.WHITE, PorterDuff.Mode.SRC_IN);
    Drawable drawable = child.getBackground();
    if (drawable != null) {
        drawable.draw(canvas);
    }
    child.draw(canvas);
    // 销毁绘制缓存,避免内存泄漏
    child.destroyDrawingCache();
    return bitmap;
}

额外优化建议

  • 内存优化:如果需要生成大量自定义Marker图标,可以加入LruCache缓存机制,避免重复生成相同用户名的Bitmap,减少内存消耗。
  • 调试优化:把调试用的Toast换成Log输出,频繁弹出Toast会影响用户体验。
  • 性能优化:生成Bitmap的操作如果耗时较多,可以放到子线程中处理,避免阻塞主线程导致UI卡顿。

内容的提问来源于stack exchange,提问作者Jimmy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:08:40