能否直接在onClick回调监听器中实现debounce防抖功能?
自定义MapView缩放监听器内置防抖实现方案
可以直接在自定义监听器内部通过Android原生Handler实现防抖逻辑,完全不需要依赖协程实验API,同时封装度更高,调用更简洁。
改造后的完整代码
import android.os.Handler import android.os.Looper import android.view.View import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleOwner import java.lang.ref.WeakReference class ZoomMapListener( mapView: MapView, private val zoom: Zoom, // 支持自定义防抖间隔,默认500ms private val debounceDelay: Long = 500L, // 可选传入生命周期自动解绑,避免内存泄漏 lifecycle: Lifecycle? = null ) : View.OnClickListener { private val localMapView = WeakReference(mapView) private var clickCount = 0 private val mainHandler = Handler(Looper.getMainLooper()) private val moveCameraTask = Runnable { moveCamera() } init { // 传入生命周期的话,在页面销毁时自动清理待执行任务 lifecycle?.addObserver(object : DefaultLifecycleObserver { override fun onDestroy(owner: LifecycleOwner) { super.onDestroy(owner) mainHandler.removeCallbacks(moveCameraTask) } }) } override fun onClick(view: View?) { clickCount++ // 每次点击都重置防抖计时器 mainHandler.removeCallbacks(moveCameraTask) mainHandler.postDelayed(moveCameraTask, debounceDelay) } private fun moveCamera() { val mapView = localMapView.get() ?: return val currentCamera = mapView.map.cameraPosition val targetZoom = if (zoom == Zoom.IN) { currentCamera.zoom + 1.0f * clickCount } else { currentCamera.zoom - 1.0f * clickCount } val newCamera = CameraPosition( currentCamera.target, targetZoom, currentCamera.azimuth, currentCamera.tilt ) clickCount = 0 mapView.map.move(newCamera, Animation(Animation.Type.SMOOTH, 0.5f), null) } // 提供手动取消待执行任务的入口 fun cancelPendingTask() { mainHandler.removeCallbacks(moveCameraTask) } } enum class Zoom { IN, OUT }
调用方式
不需要额外编写View扩展函数,也不需要手动传入协程作用域,符合原生点击事件的使用习惯:
// 基础调用 zoomInMapButton.setOnClickListener(ZoomMapListener(mapView, Zoom.IN)) zoomOutMapButton.setOnClickListener(ZoomMapListener(mapView, Zoom.OUT)) // 带自定义参数的调用(推荐) zoomInMapButton.setOnClickListener(ZoomMapListener( mapView = mapView, zoom = Zoom.IN, debounceDelay = 600L, lifecycle = viewLifecycleOwner.lifecycle ))
优化说明
- 完全移除了协程实验API依赖,仅用Android原生组件实现防抖逻辑,稳定性更高
- 所有缩放相关逻辑完全内聚在监听器类内部,职责更清晰,不需要额外的工具类/扩展函数
- 支持自定义防抖间隔、可选生命周期绑定,灵活性和安全性都优于原有实现
- 调用方式更简洁,和原生Android View的点击事件使用习惯完全对齐
内容的提问来源于stack exchange,提问作者memeprincess
相关产品推荐
相关产品推荐

