Network panel: disable Header ExpansionTiles when no data (#9492)

diff --git a/packages/devtools_app/lib/src/screens/network/network_request_inspector_views.dart b/packages/devtools_app/lib/src/screens/network/network_request_inspector_views.dart
index 00d2da0..831b3e5 100644
--- a/packages/devtools_app/lib/src/screens/network/network_request_inspector_views.dart
+++ b/packages/devtools_app/lib/src/screens/network/network_request_inspector_views.dart
@@ -29,12 +29,18 @@
   bottom: _rowSpacingPadding,
 );
 
-/// Helper to build ExpansionTile widgets for inspector views.
-ExpansionTile _buildTile(String title, List<Widget> children, {Key? key}) {
+/// Helper to build [ExpansionTile] widgets for inspector views.
+ExpansionTile _buildTile(
+  String title,
+  List<Widget> children, {
+  Key? key,
+  bool enabled = true,
+}) {
   return ExpansionTile(
     key: key,
     title: Text(title),
     initiallyExpanded: true,
+    enabled: enabled,
     children: children,
   );
 }
@@ -63,30 +69,70 @@
         return SelectionArea(
           child: ListView(
             children: [
-              _buildTile('General', [
-                for (final entry in general.entries)
-                  _Row(
-                    entry: entry,
-                    constraints: constraints,
-                    isErrorValue: data.didFail && entry.key == 'statusCode',
-                  ),
-              ], key: generalKey),
-              _buildTile('Response Headers', [
-                if (responseHeaders != null)
-                  for (final entry in responseHeaders.entries)
-                    _Row(entry: entry, constraints: constraints),
-              ], key: responseHeadersKey),
-              _buildTile('Request Headers', [
-                if (requestHeaders != null)
-                  for (final entry in requestHeaders.entries)
-                    _Row(entry: entry, constraints: constraints),
-              ], key: requestHeadersKey),
+              _buildHeadersTile(
+                'General',
+                general,
+                constraints,
+                key: generalKey,
+              ),
+              _buildHeadersTile(
+                'Response Headers',
+                responseHeaders,
+                constraints,
+                key: responseHeadersKey,
+              ),
+              _buildHeadersTile(
+                'Request Headers',
+                requestHeaders,
+                constraints,
+                key: requestHeadersKey,
+              ),
             ],
           ),
         );
       },
     );
   }
+
+  ExpansionTile _buildHeadersTile(
+    String title,
+    Map<String, dynamic>? headers,
+    BoxConstraints constraints, {
+    Key? key,
+  }) {
+    final hasHeaders = headers != null && headers.isNotEmpty;
+    return _buildTile(
+      title,
+      [
+        if (hasHeaders)
+          for (final entry in headers.entries)
+            _Row(
+              entry: entry,
+              constraints: constraints,
+              isErrorValue: data.didFail && entry.key == 'statusCode',
+            )
+        else
+          Container(
+            width: constraints.minWidth,
+            padding: _rowPadding,
+            child: Row(
+              crossAxisAlignment: CrossAxisAlignment.start,
+              children: [
+                Text(
+                  'No data',
+                  style: TextStyle(
+                    fontStyle: FontStyle.italic,
+                    color: Colors.grey.shade600,
+                  ),
+                ),
+              ],
+            ),
+          ),
+      ],
+      key: key,
+      enabled: hasHeaders,
+    );
+  }
 }
 
 class _Row extends StatelessWidget {
diff --git a/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md b/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md
index 6b91b87..526a25c 100644
--- a/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md
+++ b/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md
@@ -43,6 +43,8 @@
 ## Network profiler updates
 
 * Fixed layout of the "error count" badge in the tab name.
+* Fix display of "Response Headers" and "Request Headers" when there are no
+  headers.
 
 ## Logging updates
 
diff --git a/packages/devtools_app/test/screens/network/network_profiler_test.dart b/packages/devtools_app/test/screens/network/network_profiler_test.dart
index bee1cad..ff46955 100644
--- a/packages/devtools_app/test/screens/network/network_profiler_test.dart
+++ b/packages/devtools_app/test/screens/network/network_profiler_test.dart
@@ -167,14 +167,16 @@
         final ExpansionTile requestsTile = tester.widget(
           find.byKey(HttpRequestHeadersView.requestHeadersKey),
         );
-        final numRequestHeaders = data.requestHeaders?.length ?? 0;
+        // The '1' fallback is for the 'No data' row.
+        final numRequestHeaders = data.requestHeaders?.length ?? 1;
         expect(requestsTile.children.length, numRequestHeaders);
 
         // Check contents of response headers.
         final ExpansionTile responsesTile = tester.widget(
           find.byKey(HttpRequestHeadersView.responseHeadersKey),
         );
-        final numResponseHeaders = data.responseHeaders?.length ?? 0;
+        // The '1' fallback is for the 'No data' row.
+        final numResponseHeaders = data.responseHeaders?.length ?? 1;
         expect(responsesTile.children.length, numResponseHeaders);
       }