Что такое debounce в RxDart и для чего он используется?

«Что такое debounce в RxDart и для чего он используется?» — вопрос из категории Реактивное программирование, который задают на 29% собеседований Flutter Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Debounce (также debounceTime) — это оператор в RxDart, который откладывает эмиссию событий из потока до тех пор, пока не пройдет заданный интервал времени без новых событий. Это паттерн "подавления дребезга".

Основное применение в Flutter:

  • Поиск с автодополнением
  • Валидация форм
  • Обработка скролла
  • Отслеживание изменений размера окна

Пример поиска с debounce:

import 'package:rxdart/rxdart.dart';

class SearchBloc {
  final _searchController = BehaviorSubject<String>();

  // Поток с debounce 500ms
  Stream<String> get searchResults => _searchController.stream
      .debounceTime(Duration(milliseconds: 500))
      .distinct() // Игнорируем повторяющиеся значения
      .where((query) => query.length >= 3); // Минимум 3 символа

  void updateQuery(String query) {
    _searchController.add(query);
  }

  void dispose() {
    _searchController.close();
  }
}

// Использование в виджете:
StreamBuilder<String>(
  stream: searchBloc.searchResults,
  builder: (context, snapshot) {
    if (snapshot.hasData) {
      return _buildResults(snapshot.data!);
    }
    return CircularProgressIndicator();
  },
)

Отличие от throttle:

  • Debounce: ждет паузу, затем эмитит последнее значение
  • Throttle: эмитит первое значение, затем игнорирует новые в течение интервала

Практический пример с TextField:

TextField(
  onChanged: (value) {
    // Без debounce: запрос на каждый символ
    // С debounce: запрос только после остановки ввода на 500ms
    searchBloc.updateQuery(value);
  },
  decoration: InputDecoration(
    hintText: 'Search...',
    suffixIcon: Icon(Icons.search),
  ),
)

Настройка:

// С кастомной логикой
stream.debounce((event) => 
  TimerStream(event, Duration(milliseconds: event.length * 100))
)