smart_debouncer 0.0.2 copy "smart_debouncer: ^0.0.2" to clipboard
smart_debouncer: ^0.0.2 copied to clipboard

A smart debouncer that dynamically adjusts delay using Exponential Moving Average (EMA) based on actual typing speed. Perfect for autocomplete/search API optimization.

example/lib/main.dart

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

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'SmartDebouncer Demo',
      theme: ThemeData(
        colorSchemeSeed: Colors.blue,
        useMaterial3: true,
      ),
      home: const AddressSearchPage(),
    );
  }
}

/// Example page demonstrating SmartDebouncer for address autocomplete.
class AddressSearchPage extends StatefulWidget {
  const AddressSearchPage({super.key});

  @override
  State<AddressSearchPage> createState() => _AddressSearchPageState();
}

class _AddressSearchPageState extends State<AddressSearchPage> {
  final SmartDebouncer _debouncer = SmartDebouncer();
  final TextEditingController _controller = TextEditingController();

  List<String> _results = [];
  bool _isLoading = false;
  int _apiCallCount = 0;

  @override
  void dispose() {
    // IMPORTANT: Always dispose the debouncer to prevent memory leaks
    _debouncer.dispose();
    _controller.dispose();
    super.dispose();
  }

  /// Simulates an API call for address autocomplete.
  Future<List<String>> _mockSearchApi(String query) async {
    // Simulate network delay
    await Future.delayed(const Duration(milliseconds: 300));

    // Mock address results
    final addresses = [
      '123 Nguyễn Huệ, Quận 1, TP.HCM',
      '456 Lê Lợi, Quận 1, TP.HCM',
      '789 Trần Hưng Đạo, Quận 5, TP.HCM',
      '101 Điện Biên Phủ, Quận Bình Thạnh, TP.HCM',
      '202 Võ Văn Tần, Quận 3, TP.HCM',
      '303 Hai Bà Trưng, Quận 1, TP.HCM',
      '404 Nguyễn Thị Minh Khai, Quận 3, TP.HCM',
      '505 Cách Mạng Tháng 8, Quận 10, TP.HCM',
    ];

    return addresses
        .where((addr) => addr.toLowerCase().contains(query.toLowerCase()))
        .toList();
  }

  void _onSearchChanged(String query) {
    if (query.isEmpty) {
      setState(() {
        _results = [];
        _isLoading = false;
      });
      return;
    }

    setState(() => _isLoading = true);

    _debouncer.run(() async {
      _apiCallCount++;
      final results = await _mockSearchApi(query);

      if (mounted) {
        setState(() {
          _results = results;
          _isLoading = false;
        });
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Address Search'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // Search input
            TextField(
              controller: _controller,
              onChanged: _onSearchChanged,
              decoration: InputDecoration(
                hintText: 'Tìm kiếm địa chỉ...',
                prefixIcon: const Icon(Icons.search),
                suffixIcon: _isLoading
                    ? const Padding(
                        padding: EdgeInsets.all(12.0),
                        child: SizedBox(
                          width: 20,
                          height: 20,
                          child: CircularProgressIndicator(strokeWidth: 2),
                        ),
                      )
                    : null,
                border: const OutlineInputBorder(),
              ),
            ),

            const SizedBox(height: 8),

            // Debug info
            Container(
              padding: const EdgeInsets.all(8),
              decoration: BoxDecoration(
                color: Colors.grey.shade100,
                borderRadius: BorderRadius.circular(8),
              ),
              child: Text(
                'API calls: $_apiCallCount  |  '
                'Current delay: ${_debouncer.currentDelay}ms  |  '
                'EMA: ${_debouncer.currentEma.toStringAsFixed(1)}ms',
                style: Theme.of(context).textTheme.bodySmall,
              ),
            ),

            const SizedBox(height: 16),

            // Results
            Expanded(
              child: _results.isEmpty
                  ? Center(
                      child: Text(
                        _controller.text.isEmpty
                            ? 'Nhập địa chỉ để tìm kiếm'
                            : 'Không tìm thấy kết quả',
                        style: Theme.of(context).textTheme.bodyMedium?.copyWith(
                              color: Colors.grey,
                            ),
                      ),
                    )
                  : ListView.builder(
                      itemCount: _results.length,
                      itemBuilder: (context, index) {
                        return ListTile(
                          leading: const Icon(Icons.location_on_outlined),
                          title: Text(_results[index]),
                          onTap: () {
                            _controller.text = _results[index];
                            setState(() => _results = []);
                          },
                        );
                      },
                    ),
            ),
          ],
        ),
      ),
    );
  }
}
0
likes
160
points
95
downloads

Documentation

API reference

Publisher

verified publisherthanhdt.dev

Weekly Downloads

A smart debouncer that dynamically adjusts delay using Exponential Moving Average (EMA) based on actual typing speed. Perfect for autocomplete/search API optimization.

Homepage
Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter

More

Packages that depend on smart_debouncer