Android&RN&Flutter實戰——防抖節流函式

callme大帥發表於2021-03-11

1.背景介紹

防抖

函式防抖,這裡的抖動就是執行的意思,而一般的抖動都是持續的,多次的。假設函式持續多次執行,我們希望讓它冷靜下來再執行。也就是當持續觸發事件的時候,函式是完全不執行的,等最後一次觸發結束的一段時間之後,再去執行。

節流

節流的意思是讓函式有節制地執行,而不是毫無節制的觸發一次就執行一次。什麼叫有節制呢?就是在一段時間內,只執行一次。

2.經典舉例

  1. 防抖函式:搜尋頁面,使用者連續輸入,等停下來再去觸發搜尋介面
  2. 節流函式:防止按鈕連點

3.Android實現

  1. 程式碼實現:
object FunctionUtil {
    private const val DEFAULT_DURATION_TIME = 300L
    var timer: Timer? = null


    /**
     * 防抖函式
     */
    fun debounce(duration: Long = DEFAULT_DURATION_TIME, doThing: () -> Unit) {
        timer?.cancel()
        timer = Timer().apply {
            schedule(timerTask {
                doThing.invoke()
                timer = null
            }, duration)
        }
    }

    /**
     * 節流函式
     */
    var lastTimeMill = 0L
    fun throttle(duration: Long = DEFAULT_DURATION_TIME, continueCall: (() -> Unit)? = null, doThing: () -> Unit) {
        val currentTime = System.currentTimeMillis()
        if (currentTime - lastTimeMill > duration) {
            doThing.invoke()
            lastTimeMill = System.currentTimeMillis()
        } else {
            continueCall?.invoke()
        }
    }
}
複製程式碼
  1. 使用:
btn_sure.setOnClickListener {
    FunctionUtil.throttle {
        Log.i("nell-click", "hahah")
    }
}

btn_sure.setOnClickListener {
    FunctionUtil.throttle(500L) {
        Log.i("nell-click", "hahah")
    }
}

FunctionUtil.debounce {
	searchApi(text)
}
複製程式碼

4.RN實現

  1. 程式碼實現:
/**
 * 防抖函式
 */
function debounce(func, delay) {
  let timeout
  return function() {
    clearTimeout(timeout)
    timeout = setTimeout(() => {
      func.apply(this, arguments)
    }, delay)
  }
}

/**
 * 節流函式
 */
function throttle(func, delay) {
    let run = true
    return function () {
      if (!run) {
        return
      }
      run = false // 持續觸發的話,run一直是false,就會停在上邊的判斷那裡
      setTimeout(() => {
        func.apply(this, arguments)
        run = true // 定時器到時間之後,會把開關開啟,我們的函式就會被執行
      }, delay)
    }
}

複製程式碼
  1. 使用:
throttle(function (e) {
  console.log("nell-click")
}, 1000)


debounce(function (e) {
    searchApi(text)
}, 300)
複製程式碼

5.Flutter實現

  1. 程式碼實現:
class CommonUtil {
  static const deFaultDurationTime = 300;
  static Timer timer;

  // 防抖函式
  static debounce(Function doSomething, {durationTime = deFaultDurationTime}) {
    timer?.cancel();
    timer = new Timer(Duration(milliseconds: durationTime), () {
      doSomething?.call();
      timer = null;
    });
  }

  // 節流函式
  static const String deFaultThrottleId = 'DeFaultThrottleId';
  static Map<String, int> startTimeMap = {deFaultThrottleId: 0};
  static throttle(Function doSomething, {String throttleId = deFaultThrottleId, durationTime = deFaultDurationTime, Function continueClick}) {
    int currentTime = DateTime.now().millisecondsSinceEpoch;
    if (currentTime - (startTimeMap[throttleId] ?? 0) > durationTime) {
      doSomething?.call();
      startTimeMap[throttleId] = DateTime.now().millisecondsSinceEpoch;
    } else {
      continueClick?.call();
    }
  }
  
}
複製程式碼
  1. 使用:
GestureDetector(
      onTap: () => CommonUtil.throttle(onTap, durationTime: durationTime)
)


CommonUtil.debounce(searchApi)
複製程式碼

完結,撒花?

相關文章