3 Simple ways to use Debouncer in Flutter

By | August 26, 2024

Watch Video Tutorial

Using Simple Timer

Create a simple debouncer class

import 'package:flutter/material.dart';
import 'package:flutter_tutorials/simple_debouncer/debouncer.dart';

class SimpleDebouncer extends StatefulWidget {
  const SimpleDebouncer({super.key});

  @override
  State<SimpleDebouncer> createState() => _SimpleDebouncerState();
}

class _SimpleDebouncerState extends State<SimpleDebouncer> {
  //
  final debouncer = Debouncer(milliseconds: 300);

  void onSearchChanged(String query) {
    debouncer.run(() {
      print('Searching $query');
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Simple Debouncer'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(30),
        child: Column(
          children: [
            TextField(
              decoration: InputDecoration(
                hintText: 'Search',
              ),
              onChanged: (value) {
                onSearchChanged(value);
              },
            ),
          ],
        ),
      ),
    );
  }
}

Implementation:

import 'dart:async';
import 'package:flutter/material.dart';

class Debouncer {
  Debouncer({
    required this.milliseconds,
  });
  final int milliseconds;

  VoidCallback? action;
  Timer? _timer;

  void run(VoidCallback action) {
    if (null != _timer) {
      _timer?.cancel();
    }
    _timer = Timer(Duration(milliseconds: milliseconds), action);
  }
}

Using ValueNotifier

import 'dart:async';
import 'package:flutter/material.dart';

class SearchQueryNotifier extends ValueNotifier<String> {
  SearchQueryNotifier() : super('');

  Timer? _timer;

  void setQuery(String query) {
    if (null != _timer) {
      _timer?.cancel();
    }
    _timer = Timer(Duration(milliseconds: 300), () {
      value = query;
    });
  }
}

Implementation:

import 'package:flutter/material.dart';
import 'package:flutter_tutorials/notifier_debouncer/search_query_notifier.dart';

class NotifierDebouncer extends StatefulWidget {
  const NotifierDebouncer({super.key});

  @override
  State<NotifierDebouncer> createState() => _NotifierDebouncerState();
}

class _NotifierDebouncerState extends State<NotifierDebouncer> {
  //
  final debouncer = SearchQueryNotifier();

  @override
  void initState() {
    super.initState();
    debouncer.addListener(() {
      print('Searching ${debouncer.value}');
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Value Notifier Debouncer'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(30),
        child: Column(
          children: [
            ValueListenableBuilder(
              valueListenable: debouncer,
              builder: (context, value, child) => Text(
                'Searching ${debouncer.value}',
              ),
            ),
            const SizedBox(height: 30),
            TextField(
              decoration: InputDecoration(
                hintText: 'Search',
              ),
              onChanged: (value) {
                debouncer.setQuery(value);
              },
            ),
          ],
        ),
      ),
    );
  }
}

Using “Simple Debouncer” package

First Add easy_debouncer package in your dependencies

https://pub.dev/packages/easy_debounce

import 'package:easy_debounce/easy_debounce.dart';
import 'package:flutter/material.dart';

class EasyDebouncer extends StatefulWidget {
  const EasyDebouncer({super.key});

  @override
  State<EasyDebouncer> createState() => _EasyDebouncerState();
}

class _EasyDebouncerState extends State<EasyDebouncer> {
  //
  String query = '';

  void runSearch() {
    EasyDebounce.debounce(
      'search-debouncer',
      const Duration(milliseconds: 300),
      () {
        print('Searching... $query');
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Easy Debouncer'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(30),
        child: Column(
          children: [
            TextField(
              decoration: InputDecoration(
                hintText: 'Search',
              ),
              onChanged: (value) {
                query = value;
                runSearch();
              },
            ),
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    super.dispose();
    EasyDebounce.cancel('search-debouncer');
  }
}

Source Code

https://github.com/MrVipinVijayan/flutter_tutorials/tree/feat/debounce

Leave a Reply

Your email address will not be published. Required fields are marked *