如何在Kotlin中为clusterManager.clusterMarkerCollection创建InfoWindowAdapter
通用解决方案
针对地图聚类库ClusterInfoWindowAdapter仅传入原生MARKER类型的问题,通用的解决思路都是建立原生Marker与自定义实体的绑定关系,主流实现方案有三种:
方案1:维护全局映射表
- 初始化聚类渲染器时,在
onClusterRendered、onClusterItemRendered回调中,将生成的Marker作为key,对应的Cluster<InfoItem>(聚合簇实体)或单个InfoItem(标记项实体)作为value,存入HashMap<Marker, Object>全局映射 - 实现
ClusterInfoWindowAdapter时,拿到传入的MARKER参数后,直接从映射表中取出对应实体:判断为聚合簇类型时,调用getItems()方法获取所有子InfoItem列表,即可渲染聚合簇的列表式InfoWindow;判断为单个标记项时,直接渲染单条信息即可 - 注意页面销毁时需清空映射表,避免持有Marker引用导致内存泄漏
示例伪代码:
// 全局映射表 private val markerBindMap = hashMapOf<Marker, Any>() // 渲染回调中存储绑定关系 override fun onClusterRendered(cluster: Cluster<InfoItem>, marker: Marker) { markerBindMap[marker] = cluster } override fun onClusterItemRendered(item: InfoItem, marker: Marker) { markerBindMap[marker] = item } // InfoWindowAdapter中取值渲染 override fun getInfoContents(marker: Marker): View? { return when(val bindEntity = markerBindMap[marker]) { is Cluster<*> -> buildClusterListWindow((bindEntity as Cluster<InfoItem>).items) is InfoItem -> buildSingleItemWindow(bindEntity) else -> null } }
方案2:使用Marker的Tag属性存储(更推荐)
- 绝大多数地图SDK的Marker都支持
setTag()/getTag()方法存储自定义数据,不需要自己维护映射表,逻辑更简洁 - 渲染聚合簇/单个标记时,直接把对应实体设置为Marker的Tag,后续在
ClusterInfoWindowAdapter中直接取marker.tag即可得到绑定的实体,后续逻辑和映射表方案完全一致 - 优势是不需要手动维护存储结构,Marker被SDK回收时Tag关联的引用也会自动释放,不会出现内存泄漏问题
- 多图层叠加场景下注意做好Tag的类型判断,避免类型转换异常
方案3:封装自定义适配器转接层
如果需要彻底规避每次都做类型判断的重复代码,可以自己封装一层中间转接层:
- 先定义业务层使用的自定义适配器接口,直接接收
Cluster<InfoItem>和InfoItem类型参数 - 实现原生
ClusterInfoWindowAdapter作为转接层,内部完成Marker到自定义实体的转换,再分发到自定义适配器的对应方法 - 上层业务仅需实现自定义适配器即可,不需要接触原生MARKER类型
示例伪代码:
// 业务层自定义适配器 interface CustomClusterInfoAdapter { fun getClusterWindow(cluster: Cluster<InfoItem>): View? fun getItemWindow(item: InfoItem): View? } // 原生接口转接层 class InfoWindowBridge( private val businessAdapter: CustomClusterInfoAdapter ) : ClusterInfoWindowAdapter { override fun getInfoContents(marker: Marker): View? { return when(val entity = marker.tag) { is Cluster<*> -> businessAdapter.getClusterWindow(entity as Cluster<InfoItem>) is InfoItem -> businessAdapter.getItemWindow(entity) else -> null } } }
内容的提问来源于stack exchange,提问作者Bungles
相关产品推荐
相关产品推荐

