| <!-- | |
| Copyright 2025 The Flutter Authors | |
| Use of this source code is governed by a BSD-style license that can be | |
| found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. | |
| --> | |
| # Shared DevTools Components | |
| This package contains UI, utility, and service components from | |
| [Dart & Flutter DevTools](https://docs.flutter.dev/tools/devtools) that can | |
| be shared between DevTools, DevTools extensions, and other tooling surfaces that need | |
| the same logic or styling. | |
| ## Usage | |
| The following will add the package as a dependency to your `pubspec.yaml` (and run an | |
| implicit `flutter pub get`): | |
| ```console | |
| $ flutter pub add devtools_app_shared | |
| ``` | |
| Import the component library that you need: | |
| ```dart | |
| import 'package:devtools_app_shared/service.dart'; | |
| import 'package:devtools_app_shared/service_extensions.dart' as extensions; | |
| import 'package:devtools_app_shared/ui.dart'; | |
| import 'package:devtools_app_shared/utils.dart'; | |
| ``` | |
| ### Examples | |
| 1. Set and access global variables. | |
| ```dart | |
| import 'package:devtools_app_shared/utils.dart'; | |
| MyCoolClass get coolClass => globals[MyCoolClass] as MyCoolClass; | |
| void main() { | |
| // Creates a globally accessible variable (`globals[ServiceManager]`); | |
| setGlobal(MyCoolClass, MyCoolClass()); | |
| coolClass.foo(); | |
| } | |
| ``` | |
| 2. Use utilities like the `AutoDisposeMixin`, which supports adding listeners | |
| that will automatically dispose as part of the `StatefulWidget` lifecycle. | |
| ```dart | |
| import 'package:devtools_app_shared/utils.dart'; | |
| class MyStatefulWidget extends StatefulWidget { | |
| const MyStatefulWidget({super.key}); | |
| @override | |
| State<MyStatefulWidget> createState() => _MyStatefulWidgetState(); | |
| } | |
| class _MyStatefulWidgetState extends State<MyStatefulWidget> | |
| with AutoDisposeMixin { | |
| var foo = 'hi'; | |
| @override | |
| void initState() { | |
| super.initState(); | |
| addAutoDisposeListener(someListenable, () { | |
| setState(() { | |
| foo = '$foo hi'; | |
| }); | |
| }); | |
| } | |
| @override | |
| Widget build(BuildContext context) { | |
| return Text(foo); | |
| } | |
| } | |
| ``` | |
| 3. Access shared UI components and styling. | |
| ```dart | |
| import 'package:devtools_app_shared/ui.dart'; | |
| ... | |
| @override | |
| Widget build(BuildContext context) { | |
| return RoundedOutlinedBorder( // Shared component | |
| child: Column( | |
| children: [ | |
| AreaPaneHeader( // Shared component | |
| roundedTopBorder: false, | |
| includeTopBorder: false, | |
| title: Text('This is a section header'), | |
| ), | |
| Expanded( | |
| child: FooWidget( | |
| child: Text( | |
| 'Foo', | |
| style: Theme.of(context).subtleTextStyle, // Shared style | |
| ), | |
| ), | |
| ), | |
| ], | |
| ), | |
| ); | |
| } | |
| ``` | |
| 4. VM service management, including access to isolates and service extensions. | |
| ```dart | |
| import 'package:devtools_app_shared/service.dart'; | |
| import 'package:devtools_app_shared/service_extensions.dart' as extensions; | |
| import 'package:devtools_shared/service.dart'; | |
| void main() { | |
| final serviceManager = ServiceManager(); | |
| // Use the [connectedState] notifier to listen for connection updates. | |
| serviceManager.connectedState.addListener(() { | |
| if (serviceManager.connectedState.value.connected) { | |
| print('Manager connected to VM service'); | |
| } else { | |
| print('Manager not connected to VM service'); | |
| } | |
| }); | |
| // To get a [VmService] object from a vm service URI, consider importing | |
| // `package:devtools_shared/service.dart` from `package:devtools_shared`. | |
| final finishedCompleter = Completer<void>(); | |
| final vmService = await connect<VmService>( | |
| uri: Uri.parse(vmServiceUri), | |
| finishedCompleter: finishedCompleter, | |
| serviceFactory: VmService.defaultFactory, | |
| ); | |
| await serviceManager.vmServiceOpened( | |
| vmService, | |
| onClosed: finishedCompleter.future, | |
| ); | |
| // Get a service extension state. | |
| final ValueListenable<ServiceExtensionState> performanceOverlayEnabled = | |
| serviceManager.manager.serviceExtensionManager.getServiceExtensionState( | |
| extensions.performanceOverlay.extension, | |
| ); | |
| // Set a service extension state. | |
| await serviceManager.manager.serviceExtensionManager.setServiceExtensionState( | |
| extensions.performanceOverlay.extension, | |
| enabled: true, | |
| value: true, | |
| ); | |
| // Access isolates. | |
| final myIsolate = serviceManager.isolateManager.mainIsolate.value; | |
| // Etc. | |
| } | |
| ``` | |
| ## Issues & feedback | |
| This package is developed as part of the larger | |
| [flutter/devtools](https://github.com/flutter/devtools) project. | |
| Please report any issues or feedback there. | |
| ## Supported Flutter versions | |
| This package follows the `flutter/packages` | |
| [policy](https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#supported-flutter-versions) | |
| for supported Flutter versions, which states that a package will support the latest `stable` | |
| version of Flutter, as well as the current `master`. In practice, this package will often | |
| support older versions as well, as minimum version requirements are generally only updated | |
| when there is a specific need, such as using a new DevTools or Flutter feature. |