@@ -228,6 +228,27 @@ abstract class AutocompleteView<QueryT extends AutocompleteQuery, ResultT extend
228
228
notifyListeners ();
229
229
}
230
230
231
+ /// Completes in a later microtask, returning true if evaluation
232
+ /// of the current query should stop and false if it should continue.
233
+ ///
234
+ /// The deferral to a later microtask allows other code in the app to run.
235
+ /// A long CPU-intensive loop should call this regularly
236
+ /// (e.g. every 1000 iterations) so that the UI remains responsive.
237
+ @protected
238
+ Future <bool > shouldStop () async {
239
+ final query = _query;
240
+ await Future (() {});
241
+
242
+ // If the query has changed, stop work on the old query.
243
+ if (query != _query) return true ;
244
+
245
+ // If there are no listeners to get the result, stop work.
246
+ // This happens in particular if [dispose] was called.
247
+ if (! hasListeners) return true ;
248
+
249
+ return false ;
250
+ }
251
+
231
252
Future <List <ResultT >?> _computeResults () async {
232
253
assert (_query != null );
233
254
final query = _query! ;
@@ -237,12 +258,9 @@ abstract class AutocompleteView<QueryT extends AutocompleteQuery, ResultT extend
237
258
final iterator = data.iterator;
238
259
bool isDone = false ;
239
260
while (! isDone) {
240
- // CPU perf: End this task; enqueue a new one for resuming this work
241
- await Future (() {});
242
-
243
- if (query != _query || ! hasListeners) { // false if [dispose] has been called.
244
- return null ;
245
- }
261
+ assert (_query == query);
262
+ if (await shouldStop ()) return null ;
263
+ assert (_query == query);
246
264
247
265
for (int i = 0 ; i < 1000 ; i++ ) {
248
266
if (! iterator.moveNext ()) {
0 commit comments