add the ability to start and stop device polling
diff --git a/packages/flutter_tools/lib/src/device.dart b/packages/flutter_tools/lib/src/device.dart index 04562ad..df00d2b 100644 --- a/packages/flutter_tools/lib/src/device.dart +++ b/packages/flutter_tools/lib/src/device.dart
@@ -4,12 +4,14 @@ import 'dart:async'; -import 'android/device_android.dart'; +import 'android/android_device.dart'; import 'application_package.dart'; import 'base/common.dart'; +import 'base/utils.dart'; import 'build_configuration.dart'; import 'globals.dart'; -import 'ios/device_ios.dart'; +import 'ios/devices.dart'; +import 'ios/simulators.dart'; import 'toolchain.dart'; /// A class to get all available devices. @@ -18,27 +20,9 @@ /// of their methods are invoked. DeviceManager() { // Register the known discoverers. - _deviceDiscoverers.add(new AndroidDeviceDiscovery()); - _deviceDiscoverers.add(new IOSDeviceDiscovery()); - _deviceDiscoverers.add(new IOSSimulatorDiscovery()); - } - - Future _init() { - if (_initedCompleter == null) { - _initedCompleter = new Completer(); - - Future.forEach(_deviceDiscoverers, (DeviceDiscovery discoverer) { - if (!discoverer.supportsPlatform) - return null; - return discoverer.init(); - }).then((_) { - _initedCompleter.complete(); - }).catchError((error, stackTrace) { - _initedCompleter.completeError(error, stackTrace); - }); - } - - return _initedCompleter.future; + _deviceDiscoverers.add(new AndroidDevices()); + _deviceDiscoverers.add(new IOSDevices()); + _deviceDiscoverers.add(new IOSSimulators()); } List<DeviceDiscovery> _deviceDiscoverers = <DeviceDiscovery>[]; @@ -46,8 +30,6 @@ /// A user-specified device ID. String specifiedDeviceId; - Completer _initedCompleter; - bool get hasSpecifiedDeviceId => specifiedDeviceId != null; /// Return the device with the matching ID; else, complete the Future with @@ -75,8 +57,6 @@ /// Return the list of all connected devices. Future<List<Device>> getAllConnectedDevices() async { - await _init(); - return _deviceDiscoverers .where((DeviceDiscovery discoverer) => discoverer.supportsPlatform) .expand((DeviceDiscovery discoverer) => discoverer.devices) @@ -87,10 +67,60 @@ /// An abstract class to discover and enumerate a specific type of devices. abstract class DeviceDiscovery { bool get supportsPlatform; - Future init(); List<Device> get devices; } +/// A [DeviceDiscovery] implementation that uses polling to discover device adds +/// and removals. +abstract class PollingDeviceDiscovery extends DeviceDiscovery { + PollingDeviceDiscovery(this.name); + + static const Duration _pollingDuration = const Duration(seconds: 4); + + final String name; + ItemListNotifier<Device> _items; + Timer _timer; + + List<Device> pollingGetDevices(); + + void startPolling() { + if (_timer == null) { + if (_items == null) + _items = new ItemListNotifier<Device>(); + _timer = new Timer.periodic(_pollingDuration, (Timer timer) { + _items.updateWithNewList(pollingGetDevices()); + }); + } + } + + void stopPolling() { + _timer?.cancel(); + _timer = null; + } + + List<Device> get devices { + if (_items == null) + _items = new ItemListNotifier<Device>.from(pollingGetDevices()); + return _items.items; + } + + Stream<Device> get onAdded { + if (_items == null) + _items = new ItemListNotifier<Device>(); + return _items.onAdded; + } + + Stream<Device> get onRemoved { + if (_items == null) + _items = new ItemListNotifier<Device>(); + return _items.onRemoved; + } + + void dispose() => stopPolling(); + + String toString() => '$name device discovery'; +} + abstract class Device { Device(this.id); @@ -139,6 +169,16 @@ /// Stop an app package on the current device. Future<bool> stopApp(ApplicationPackage app); + int get hashCode => id.hashCode; + + bool operator ==(dynamic other) { + if (identical(this, other)) + return true; + if (other is! Device) + return false; + return id == other.id; + } + String toString() => '$runtimeType $id'; }