import 'dart:async'; import 'package:flutter/foundation.dart'; import 'models.dart'; import 'service.dart'; class BankSearchProvider extends ChangeNotifier { BankSearchProvider(this.service); final DestinationService service; Timer? _timer; Completer? _abort; int _generation = 0; bool _disposed = false, loading = false; String query = ''; List results = []; DestinationIssue? error; void search(String value) { _timer?.cancel(); if (_abort != null && !_abort!.isCompleted) _abort!.complete(); _abort = null; final generation = ++_generation; query = value; results = []; error = null; loading = false; if (value.trim().length >= 2) { _timer = Timer( const Duration(milliseconds: 350), () => _lookup(value, generation), ); } notifyListeners(); } Future _lookup(String value, int generation) async { loading = true; notifyListeners(); try { final abort = Completer(); _abort = abort; final rows = await service.banks(value, abortTrigger: abort.future); if (_disposed || generation != _generation) return; results = rows; if (rows.isEmpty) error = DestinationIssue.invalid; } on DestinationException catch (e) { if (!_disposed && generation == _generation) error = e.issue; } catch (_) { if (!_disposed && generation == _generation) error = DestinationIssue.unavailable; } if (_disposed || generation != _generation) return; loading = false; notifyListeners(); } @override void dispose() { _disposed = true; _generation++; _timer?.cancel(); if (_abort != null && !_abort!.isCompleted) _abort!.complete(); super.dispose(); } }