android

android view事件去抖动

2020-08-04  本文已影响0人  WLHere

用动态代理实现去抖动的工具类

使用方法

  1. 通过扩展使用

findViewById<View>(R.id.btn).setOnClickListener(View.OnClickListener { }.debounce())

  1. 直接通过方法调用使用

findViewById<View>(R.id.btn).setOnClickListener(DebounceUtil.debounce(View.OnClickListener { }))

源码如下:
https://github.com/WLHere/Snippet/blob/master/util/DebounceUtil.kt

package com.bwl.test

import android.os.SystemClock
import java.lang.reflect.InvocationHandler
import java.lang.reflect.Method
import java.lang.reflect.Proxy

/**
 * Created by WLHere on 2020/8/4
 */

fun <R> Any?.debounce(): R {
    return DebounceUtil.debounce(this)
}

fun <R> Any?.debounce(interval: Long): R {
    return DebounceUtil.debounce(this, interval)
}

object DebounceUtil {
    private const val DEFAULT_DURATION = 500L// 默认的时间

    fun <R> debounce(listener: Any?): R {
        return debounce(listener, DEFAULT_DURATION)
    }

    fun <R> debounce(listener: Any?, timeInterval: Long): R {
        if (listener == null) {
            return listener as R
        }
        val messages = listener.javaClass.interfaces
        require(!messages.isNullOrEmpty()) { "必须实现一个接口" }

        return Proxy.newProxyInstance(listener.javaClass.classLoader, messages, object :
            InvocationHandler {
            private val results = HashMap<Method, Pair<Long, Any?>>()

            @Throws(Throwable::class)
            override fun invoke(proxy: Any, method: Method, args: Array<Any>): Any? {
                var result = results[method]
                val curTime = SystemClock.elapsedRealtime()
                if (result == null || curTime - result.first > timeInterval) {
                    result = Pair(curTime, method.invoke(listener, *args))
                    results[method] = result
                }
                return result.second
            }
        }) as R
    }
}
上一篇下一篇

猜你喜欢

热点阅读