|
| 1 | +--- |
| 2 | +title: DevTools Extension |
| 3 | +prev: |
| 4 | + text: 'Testing' |
| 5 | + link: '/documentation/get_it/testing' |
| 6 | +next: |
| 7 | + text: 'Flutter Previews' |
| 8 | + link: '/documentation/get_it/flutter_previews' |
| 9 | +--- |
| 10 | + |
| 11 | +<div style="display: flex; align-items: center; gap: 1rem; margin-bottom: 2rem;"> |
| 12 | + <img src="/images/get_it.svg" alt="get_it logo" width="100" /> |
| 13 | + <h1 style="margin: 0;">DevTools Extension</h1> |
| 14 | +</div> |
| 15 | + |
| 16 | +**get_it** includes a DevTools extension that lets you visualize and inspect all registered objects in your running Flutter app in real-time. |
| 17 | + |
| 18 | +<strong>Key features:</strong> |
| 19 | +<ul style="list-style: none; padding-left: 0;"> |
| 20 | + <li style="padding-left: 1.5em; text-indent: -1.5em;">✅ <strong>View all registrations</strong> - See every object registered in get_it across all scopes</li> |
| 21 | + <li style="padding-left: 1.5em; text-indent: -1.5em;">✅ <strong>Inspect instance state</strong> - View the toString() output of created instances</li> |
| 22 | + <li style="padding-left: 1.5em; text-indent: -1.5em;">✅ <strong>Track registration details</strong> - Type, scope, mode, async status, ready state, creation status</li> |
| 23 | + <li style="padding-left: 1.5em; text-indent: -1.5em;">✅ <strong>Real-time updates</strong> - Automatically refreshes when registrations change (with debug events enabled)</li> |
| 24 | +</ul> |
| 25 | + |
| 26 | +--- |
| 27 | + |
| 28 | +## Setup |
| 29 | + |
| 30 | +### 1. Enable Debug Events |
| 31 | + |
| 32 | +In your app's `main.dart`, enable debug events before running your app: |
| 33 | + |
| 34 | +```dart |
| 35 | +void main() { |
| 36 | + GetIt.instance.debugEventsEnabled = true; |
| 37 | +
|
| 38 | + // ... configure your dependencies |
| 39 | + configureDependencies(); |
| 40 | +
|
| 41 | + runApp(MyApp()); |
| 42 | +} |
| 43 | +``` |
| 44 | + |
| 45 | +::: tip Why Enable Debug Events? |
| 46 | +When `debugEventsEnabled` is `true`, get_it sends events to DevTools whenever registrations change, allowing the extension to automatically update. Without this, you'll need to manually refresh the extension to see changes. |
| 47 | +::: |
| 48 | + |
| 49 | +::: warning Debug Mode Only |
| 50 | +The DevTools extension only works in debug mode. In release builds, the extension is not available and debug events have no effect. |
| 51 | +::: |
| 52 | + |
| 53 | +### 2. Run Your App in Debug Mode |
| 54 | + |
| 55 | +```bash |
| 56 | +flutter run |
| 57 | +``` |
| 58 | + |
| 59 | +### 3. Open DevTools in Browser |
| 60 | + |
| 61 | +The get_it extension currently **only works in the browser-based DevTools**, not in IDE-embedded DevTools. |
| 62 | + |
| 63 | +When you run your app, Flutter will display a message like: |
| 64 | + |
| 65 | +``` |
| 66 | +The Flutter DevTools debugger and profiler is available at: http://127.0.0.1:9100 |
| 67 | +``` |
| 68 | + |
| 69 | +Open that URL in your browser. |
| 70 | + |
| 71 | +### 4. Enable the Extension |
| 72 | + |
| 73 | +1. In DevTools, click the **Extensions** button (puzzle piece icon) in the top right corner |
| 74 | +2. Find the `get_it` extension in the list and enable it |
| 75 | +3. The "get_it" tab will appear in the main DevTools navigation |
| 76 | + |
| 77 | +### 5. Open the get_it Tab |
| 78 | + |
| 79 | +Click on the "get_it" tab to view all your registrations. |
| 80 | + |
| 81 | +--- |
| 82 | + |
| 83 | +## Understanding the Registration Table |
| 84 | + |
| 85 | +The DevTools extension displays all registered objects in a table with the following columns: |
| 86 | + |
| 87 | + |
| 88 | +*The get_it DevTools extension showing all registered objects in a running app* |
| 89 | + |
| 90 | +| Column | Description | |
| 91 | +|--------|-------------| |
| 92 | +| **Type** | The registered type (class name) | |
| 93 | +| **Instance Name** | The instance name if using named registrations, otherwise empty | |
| 94 | +| **Scope** | The scope this registration belongs to (e.g., `baseScope` for the default scope) | |
| 95 | +| **Mode** | The registration type: `constant` (singleton), `lazy` (lazy singleton), `alwaysNew` (factory), or `cachedFactory` | |
| 96 | +| **Async** | Whether this is an async registration (`true` for `registerSingletonAsync` and `registerLazySingletonAsync`) | |
| 97 | +| **Ready** | For async registrations, whether the initialization is complete | |
| 98 | +| **Created** | Whether the instance has been created (false for lazy registrations that haven't been accessed yet) | |
| 99 | +| **Instance Details** | The `toString()` output of the instance (if created) | |
| 100 | + |
| 101 | +--- |
| 102 | + |
| 103 | +## Making Instance Details Meaningful |
| 104 | + |
| 105 | +By default, Dart's `toString()` only shows the type name and instance ID (e.g., `Instance of 'UserRepository'`). To see meaningful details in the DevTools extension, **override `toString()` in your registered classes**: |
| 106 | + |
| 107 | +```dart |
| 108 | +class UserRepository { |
| 109 | + final String userId; |
| 110 | + final bool isAuthenticated; |
| 111 | +
|
| 112 | + UserRepository(this.userId, this.isAuthenticated); |
| 113 | +
|
| 114 | + @override |
| 115 | + String toString() { |
| 116 | + return 'UserRepository(userId: $userId, isAuthenticated: $isAuthenticated)'; |
| 117 | + } |
| 118 | +} |
| 119 | +``` |
| 120 | + |
| 121 | +Now in DevTools, you'll see: |
| 122 | +``` |
| 123 | +UserRepository(userId: user123, isAuthenticated: true) |
| 124 | +``` |
| 125 | + |
| 126 | +### Tips for Good toString() Implementations |
| 127 | + |
| 128 | +<ul style="list-style: none; padding-left: 0;"> |
| 129 | + <li style="padding-left: 1.5em; text-indent: -1.5em;">✅ <strong>Include key state</strong> - Show the most important properties that help you understand the object's current state</li> |
| 130 | + <li style="padding-left: 1.5em; text-indent: -1.5em;">✅ <strong>Keep it concise</strong> - Long strings are hard to read in the table. Stick to the essential information</li> |
| 131 | + <li style="padding-left: 1.5em; text-indent: -1.5em;">✅ <strong>Use descriptive names</strong> - Make it obvious what each value represents</li> |
| 132 | + <li style="padding-left: 1.5em; text-indent: -1.5em;">✅ <strong>Include enum states</strong> - If your object has states or modes, include them</li> |
| 133 | +</ul> |
| 134 | + |
| 135 | +**Example for a media player:** |
| 136 | + |
| 137 | +```dart |
| 138 | +class PlayerManager { |
| 139 | + bool isPlaying; |
| 140 | + String? currentTrack; |
| 141 | + Duration position; |
| 142 | + Duration duration; |
| 143 | +
|
| 144 | + @override |
| 145 | + String toString() { |
| 146 | + final posStr = '${position.inMinutes}:${(position.inSeconds % 60).toString().padLeft(2, '0')}'; |
| 147 | + final durStr = '${duration.inMinutes}:${(duration.inSeconds % 60).toString().padLeft(2, '0')}'; |
| 148 | +
|
| 149 | + return 'PlayerManager(' |
| 150 | + 'playing: $isPlaying, ' |
| 151 | + 'track: ${currentTrack ?? 'none'}, ' |
| 152 | + 'position: $posStr/$durStr' |
| 153 | + ')'; |
| 154 | + } |
| 155 | +} |
| 156 | +``` |
| 157 | + |
| 158 | +This shows: `PlayerManager(playing: true, track: My Song, position: 2:34/4:15)` |
| 159 | + |
| 160 | +--- |
| 161 | + |
| 162 | +## Refreshing the View |
| 163 | + |
| 164 | +- **With debug events enabled**: The view automatically updates when registrations change |
| 165 | +- **Without debug events**: Click the **Refresh** button in the extension to manually update the view |
| 166 | +- **Manual refresh**: You can always click Refresh to ensure you're seeing the latest state |
| 167 | + |
| 168 | +--- |
| 169 | + |
| 170 | +## Troubleshooting |
| 171 | + |
| 172 | +### The get_it tab doesn't appear |
| 173 | + |
| 174 | +<ul style="list-style: none; padding-left: 0;"> |
| 175 | + <li style="padding-left: 1.5em; text-indent: -1.5em;">➜ Make sure you're using <strong>browser-based DevTools</strong>, not IDE-embedded DevTools</li> |
| 176 | + <li style="padding-left: 1.5em; text-indent: -1.5em;">➜ Verify the extension is <strong>enabled</strong> in the Extensions menu (puzzle piece icon)</li> |
| 177 | + <li style="padding-left: 1.5em; text-indent: -1.5em;">➜ Ensure your app is running in <strong>debug mode</strong></li> |
| 178 | +</ul> |
| 179 | + |
| 180 | +### The extension shows no registrations |
| 181 | + |
| 182 | +<ul style="list-style: none; padding-left: 0;"> |
| 183 | + <li style="padding-left: 1.5em; text-indent: -1.5em;">➜ Make sure you've actually <strong>registered objects</strong> in your app</li> |
| 184 | + <li style="padding-left: 1.5em; text-indent: -1.5em;">➜ Click the <strong>Refresh button</strong> to manually update the view</li> |
| 185 | + <li style="padding-left: 1.5em; text-indent: -1.5em;">➜ Verify you're looking at the correct <strong>DevTools instance</strong> for your running app</li> |
| 186 | +</ul> |
| 187 | + |
| 188 | +### The extension doesn't auto-update |
| 189 | + |
| 190 | +<ul style="list-style: none; padding-left: 0;"> |
| 191 | + <li style="padding-left: 1.5em; text-indent: -1.5em;">➜ Check that <code>debugEventsEnabled = true</code> is set <strong>before</strong> any registrations</li> |
| 192 | + <li style="padding-left: 1.5em; text-indent: -1.5em;">➜ Use the manual <strong>Refresh button</strong> if auto-updates aren't working</li> |
| 193 | +</ul> |
| 194 | + |
| 195 | +--- |
| 196 | + |
| 197 | +## Use Cases |
| 198 | + |
| 199 | +### During Development |
| 200 | + |
| 201 | +- **Verify registrations** - Ensure all required services are registered at startup |
| 202 | +- **Debug initialization** - Check which async singletons are ready |
| 203 | +- **Inspect state** - View the current state of your services and models |
| 204 | +- **Understand scopes** - See which objects belong to which scope |
| 205 | + |
| 206 | +### During Testing |
| 207 | + |
| 208 | +- **Verify test setup** - Ensure mocks are registered correctly |
| 209 | +- **Debug flaky tests** - Check if objects are being created multiple times |
| 210 | +- **Scope isolation** - Verify that test scopes are working as expected |
| 211 | + |
| 212 | +### During Debugging |
| 213 | + |
| 214 | +- **Track down bugs** - Inspect service state when bugs occur |
| 215 | +- **Verify lifecycle** - Check if lazy singletons are created when expected |
| 216 | +- **Monitor changes** - Watch how registrations change as you navigate your app |
| 217 | + |
| 218 | +--- |
| 219 | + |
| 220 | +## Learn More |
| 221 | + |
| 222 | +- [Testing with get_it](/documentation/get_it/testing) - Learn how to test your get_it registrations |
| 223 | +- [Scopes](/documentation/get_it/scopes) - Understand how scopes work |
| 224 | +- [Async Objects](/documentation/get_it/async_objects) - Learn about async initialization |
| 225 | +- [Official Flutter DevTools Documentation](https://docs.flutter.dev/tools/devtools/extensions) |
0 commit comments