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:intl/intl.dart';
|
||||||
import 'package:quiver/time.dart';
|
import 'package:quiver/time.dart';
|
||||||
|
|
||||||
|
import '../globals.dart';
|
||||||
import 'context.dart';
|
import 'context.dart';
|
||||||
import 'file_system.dart';
|
import 'file_system.dart';
|
||||||
import 'platform.dart';
|
import 'platform.dart';
|
||||||
@ -216,3 +217,42 @@ class Uuid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Clock get clock => context.putIfAbsent(Clock, () => const Clock());
|
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;
|
final String name;
|
||||||
ItemListNotifier<Device> _items;
|
ItemListNotifier<Device> _items;
|
||||||
Timer _timer;
|
Poller _poller;
|
||||||
|
|
||||||
Future<List<Device>> pollingGetDevices();
|
Future<List<Device>> pollingGetDevices();
|
||||||
|
|
||||||
void startPolling() {
|
void startPolling() {
|
||||||
if (_timer == null) {
|
if (_poller == null) {
|
||||||
_items ??= new ItemListNotifier<Device>();
|
_items ??= new ItemListNotifier<Device>();
|
||||||
bool _fetchingDevices = false;
|
|
||||||
_timer = new Timer.periodic(_pollingInterval, (Timer timer) async {
|
_poller = new Poller(() async {
|
||||||
if (_fetchingDevices) {
|
|
||||||
printTrace('Skipping device poll: already in progress');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_fetchingDevices = true;
|
|
||||||
try {
|
try {
|
||||||
final List<Device> devices = await pollingGetDevices().timeout(_pollingTimeout);
|
final List<Device> devices = await pollingGetDevices().timeout(_pollingTimeout);
|
||||||
_items.updateWithNewList(devices);
|
_items.updateWithNewList(devices);
|
||||||
} on TimeoutException {
|
} on TimeoutException {
|
||||||
printTrace('Device poll timed out.');
|
printTrace('Device poll timed out.');
|
||||||
} finally {
|
|
||||||
_fetchingDevices = false;
|
|
||||||
}
|
}
|
||||||
});
|
}, _pollingInterval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void stopPolling() {
|
void stopPolling() {
|
||||||
_timer?.cancel();
|
_poller?.cancel();
|
||||||
_timer = null;
|
_poller = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter_tools/src/base/utils.dart';
|
import 'package:flutter_tools/src/base/utils.dart';
|
||||||
import 'package:flutter_tools/src/base/version.dart';
|
import 'package:flutter_tools/src/base/version.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
@ -115,4 +117,52 @@ baz=qux
|
|||||||
expect(new Version.parse('Preview2.2'), isNull);
|
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