mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
perform the initial poll for devices quicker (#11356)
* perform the initial poll for devices quicker * add a Poller class * test the new Poller class
This commit is contained in:
parent
bbcfb8d51a
commit
a7c3bf4849
@ -10,6 +10,7 @@ import 'package:crypto/crypto.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:quiver/time.dart';
|
||||
|
||||
import '../globals.dart';
|
||||
import 'context.dart';
|
||||
import 'file_system.dart';
|
||||
import 'platform.dart';
|
||||
@ -216,3 +217,42 @@ class Uuid {
|
||||
}
|
||||
|
||||
Clock get clock => context.putIfAbsent(Clock, () => const Clock());
|
||||
|
||||
typedef Future<Null> AsyncCallback();
|
||||
|
||||
/// A [Timer] inspired class that:
|
||||
/// - has a different initial value for the first callback delay
|
||||
/// - waits for a callback to be complete before it starts the next timer
|
||||
class Poller {
|
||||
Poller(this.callback, this.pollingInterval, { this.initialDelay: Duration.ZERO }) {
|
||||
new Future<Null>.delayed(initialDelay, _handleCallback);
|
||||
}
|
||||
|
||||
final AsyncCallback callback;
|
||||
final Duration initialDelay;
|
||||
final Duration pollingInterval;
|
||||
|
||||
bool _cancelled = false;
|
||||
Timer _timer;
|
||||
|
||||
Future<Null> _handleCallback() async {
|
||||
if (_cancelled)
|
||||
return;
|
||||
|
||||
try {
|
||||
await callback();
|
||||
} catch (error) {
|
||||
printTrace('Error from poller: $error');
|
||||
}
|
||||
|
||||
if (!_cancelled)
|
||||
_timer = new Timer(pollingInterval, _handleCallback);
|
||||
}
|
||||
|
||||
/// Cancels the poller.
|
||||
void cancel() {
|
||||
_cancelled = true;
|
||||
_timer?.cancel();
|
||||
_timer = null;
|
||||
}
|
||||
}
|
||||
|
@ -116,35 +116,28 @@ abstract class PollingDeviceDiscovery extends DeviceDiscovery {
|
||||
|
||||
final String name;
|
||||
ItemListNotifier<Device> _items;
|
||||
Timer _timer;
|
||||
Poller _poller;
|
||||
|
||||
Future<List<Device>> pollingGetDevices();
|
||||
|
||||
void startPolling() {
|
||||
if (_timer == null) {
|
||||
if (_poller == null) {
|
||||
_items ??= new ItemListNotifier<Device>();
|
||||
bool _fetchingDevices = false;
|
||||
_timer = new Timer.periodic(_pollingInterval, (Timer timer) async {
|
||||
if (_fetchingDevices) {
|
||||
printTrace('Skipping device poll: already in progress');
|
||||
return;
|
||||
}
|
||||
_fetchingDevices = true;
|
||||
|
||||
_poller = new Poller(() async {
|
||||
try {
|
||||
final List<Device> devices = await pollingGetDevices().timeout(_pollingTimeout);
|
||||
_items.updateWithNewList(devices);
|
||||
} on TimeoutException {
|
||||
printTrace('Device poll timed out.');
|
||||
} finally {
|
||||
_fetchingDevices = false;
|
||||
}
|
||||
});
|
||||
}, _pollingInterval);
|
||||
}
|
||||
}
|
||||
|
||||
void stopPolling() {
|
||||
_timer?.cancel();
|
||||
_timer = null;
|
||||
_poller?.cancel();
|
||||
_poller = null;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -2,6 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter_tools/src/base/utils.dart';
|
||||
import 'package:flutter_tools/src/base/version.dart';
|
||||
import 'package:test/test.dart';
|
||||
@ -115,4 +117,52 @@ baz=qux
|
||||
expect(new Version.parse('Preview2.2'), isNull);
|
||||
});
|
||||
});
|
||||
|
||||
group('Poller', () {
|
||||
const Duration kShortDelay = const Duration(milliseconds: 100);
|
||||
|
||||
Poller poller;
|
||||
|
||||
tearDown(() {
|
||||
poller?.cancel();
|
||||
});
|
||||
|
||||
test('fires at start', () async {
|
||||
bool called = false;
|
||||
poller = new Poller(() {
|
||||
called = true;
|
||||
}, const Duration(seconds: 1));
|
||||
expect(called, false);
|
||||
await new Future<Null>.delayed(kShortDelay);
|
||||
expect(called, true);
|
||||
});
|
||||
|
||||
test('runs periodically', () async {
|
||||
// Ensure we get the first (no-delay) callback, and one of the periodic callbacks.
|
||||
int callCount = 0;
|
||||
poller = new Poller(() {
|
||||
callCount++;
|
||||
}, new Duration(milliseconds: kShortDelay.inMilliseconds ~/ 2));
|
||||
expect(callCount, 0);
|
||||
await new Future<Null>.delayed(kShortDelay);
|
||||
expect(callCount, greaterThanOrEqualTo(2));
|
||||
});
|
||||
|
||||
test('no quicker then the periodic delay', () async {
|
||||
// Make sure that the poller polls at delay + the time it took to run the callback.
|
||||
final Completer<Duration> completer = new Completer<Duration>();
|
||||
DateTime firstTime;
|
||||
poller = new Poller(() async {
|
||||
if (firstTime == null)
|
||||
firstTime = new DateTime.now();
|
||||
else
|
||||
completer.complete(new DateTime.now().difference(firstTime));
|
||||
|
||||
// introduce a delay
|
||||
await new Future<Null>.delayed(kShortDelay);
|
||||
}, kShortDelay);
|
||||
final Duration duration = await completer.future;
|
||||
expect(duration, greaterThanOrEqualTo(new Duration(milliseconds: kShortDelay.inMilliseconds * 2)));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user