debug this
diff --git a/packages/devtools_app/.flutter-plugins-dependencies b/packages/devtools_app/.flutter-plugins-dependencies
new file mode 100644
index 0000000..a015c88
--- /dev/null
+++ b/packages/devtools_app/.flutter-plugins-dependencies
@@ -0,0 +1 @@
+{"dependencyGraph":[{"name":"image_gallery_saver","dependencies":[]},{"name":"path_provider","dependencies":[]},{"name":"devtools_app","dependencies":[]}]}
\ No newline at end of file
diff --git a/packages/devtools_app/lib/src/inspector/diagnostics_node.dart b/packages/devtools_app/lib/src/inspector/diagnostics_node.dart
index 8f4b1ad..b80ff9d 100644
--- a/packages/devtools_app/lib/src/inspector/diagnostics_node.dart
+++ b/packages/devtools_app/lib/src/inspector/diagnostics_node.dart
@@ -674,19 +674,6 @@
     await (await inspectorService)
         ?.setSelectionInspector(valueRef, uiAlreadyUpdated);
   }
-
-  Future<void> getRenderObject() async {
-    if (_renderObject != null) return;
-    final service = await inspectorService;
-    _renderObject = await service.renderObject(valueRef);
-    if (isFlex && _children != null)
-      for (var i = 0; i < _children.length; ++i) {
-        final List<dynamic> children =
-            _renderObject.json['children'];
-        _children[i]._renderObject = RemoteDiagnosticsNode(
-            children[i], inspectorService, true, _children[i]);
-      }
-  }
 }
 
 class InspectorSourceLocation {
diff --git a/packages/devtools_app/lib/src/inspector/flutter/inspector_screen_details_tab.dart b/packages/devtools_app/lib/src/inspector/flutter/inspector_screen_details_tab.dart
index ff4a438..dc9660d 100644
--- a/packages/devtools_app/lib/src/inspector/flutter/inspector_screen_details_tab.dart
+++ b/packages/devtools_app/lib/src/inspector/flutter/inspector_screen_details_tab.dart
@@ -106,13 +106,18 @@
   RemoteDiagnosticsNode root;
 
   void onSelectionChanged() async {
+    if (!selected.isFlex && selected.parent != null && !selected.parent.isFlex)
+      return;
     objectGroupManager.cancelNext();
+
+    // TODO(albertusangga) show loading animation when root is null?
     setState(() {
       root = null;
     });
+
     final nextObjectGroup = objectGroupManager.next;
-    if (selected ?? false) {
-      final root = await nextObjectGroup.getDetailsSubtree(
+    if (selected != null) {
+      root = await nextObjectGroup.getDetailsSubtreeWithRenderObject(
         selected,
         subtreeDepth: 1,
       );
@@ -139,6 +144,7 @@
         'flex-layout',
       );
     }
+    onSelectionChanged();
   }
 
   @override
@@ -157,12 +163,8 @@
   Widget build(BuildContext context) {
     super.build(context);
     // TODO(albertusangga): Visualize non-flex widget constraint model
-    if (selected == null ||
-        (!selected.isFlex && !(selected.parent?.isFlex ?? false)))
-      return const SizedBox();
-    final flexLayoutProperties = FlexLayoutProperties.fromDiagnostics(
-      selected.isFlex ? selected : selected.parent,
-    );
+    if (root == null) return const SizedBox();
+    final flexLayoutProperties = FlexLayoutProperties.fromDiagnostics(root);
     final highlightChild =
         selected.isFlex ? null : selected.parent.childrenNow.indexOf(selected);
     return StoryOfYourFlexWidget(
diff --git a/packages/devtools_app/lib/src/inspector/inspector_service.dart b/packages/devtools_app/lib/src/inspector/inspector_service.dart
index b43ef94..3829636 100644
--- a/packages/devtools_app/lib/src/inspector/inspector_service.dart
+++ b/packages/devtools_app/lib/src/inspector/inspector_service.dart
@@ -955,29 +955,79 @@
     ));
   }
 
-  Future<RemoteDiagnosticsNode> renderObject(InspectorInstanceRef ref) async {
-    // TODO(albertusangga): Make this new Service Extension in flutter/flutter
-    String command = '''
-      final id = '${ref.id}';
-      final instance = WidgetInspectorService.instance;
-      final Element object = WidgetInspectorService.instance.toObject(id);
-      final RenderObject renderObject = object.renderObject;
-      return instance._safeJsonEncode(
-        instance._nodeToJson(
-          renderObject.toDiagnosticsNode(),
-          _SerializationDelegate(
-            groupName: '',
-            service: instance,
-            includeProperties: true,
-          ),
-      ));
-    ''';
-    command = '((){${command.split('\n').join()})()';
-    final val = await inspectorLibrary.eval(
-      command,
-      isAlive: this,
-    );
-    return parseDiagnosticsNodeObservatory(val);
+  static const getDetailsSubtreeWithRenderObjectServiceExtensionName = 'getDetailsSubtreeWithRenderObject';
+
+  Future<RemoteDiagnosticsNode> getDetailsSubtreeWithRenderObject(RemoteDiagnosticsNode node, { int subtreeDepth = 1 }) async {
+    if (node == null) return null;
+    if (!serviceManager.serviceExtensionManager.isServiceExtensionAvailable(getDetailsSubtreeWithRenderObjectServiceExtensionName)) {
+      String command = '''
+      print('start registering...');
+      WidgetInspectorService.instance.registerServiceExtension(
+        name: 'getDetailsSubtreeWithRenderObject',
+        callback: (Map<String, String> parameters) async {
+          print('inside callback...');
+          Map<String, Object> _getDetailsSubtreeWithRenderObject(
+              String id,
+              String groupName,
+              int subtreeDepth,
+              ) {
+            final DiagnosticsNode root = WidgetInspectorService.instance.toObject(id);
+            if (root == null) {
+              return null;
+            }
+            return WidgetInspectorService.instance._nodeToJson(
+              root,
+              _SerializationDelegate(
+                  groupName: groupName,
+                  summaryTree: false,
+                  subtreeDepth: subtreeDepth,
+                  includeProperties: true,
+                  service: WidgetInspectorService.instance,
+                  addAdditionalPropertiesCallback: (node, delegate) {
+                    final Map<String, Object> additionalJson = <String, Object>{};
+                    final Object value = node.value;
+                    if (value is Element) {
+                      additionalJson['renderObject'] = value.renderObject.toDiagnosticsNode()?.toJsonMap(
+                        delegate.copyWith(
+                          subtreeDepth: 0,
+                          includeProperties: true,
+                        ),
+                      );
+                    }
+                    return additionalJson;
+                  }
+              ),
+            );
+          }
+          assert(parameters.containsKey('objectGroup'));
+          final String subtreeDepth = parameters['subtreeDepth'];
+          return <String, Object>{
+            'result': _getDetailsSubtreeWithRenderObject(
+              parameters['arg'],
+              parameters['objectGroup'],
+              subtreeDepth != null ? int.parse(subtreeDepth) : 2,
+            ),
+          };
+        },
+      );
+      print('finish registering...');
+      ''';
+      command = '((){${command.split('\n').join()}})()';
+      await inspectorLibrary.eval(
+        command,
+        isAlive: this,
+      );
+    }
+    final args = {
+      'objectGroup': groupName,
+      'arg': node.dartDiagnosticRef.id,
+      'subtreeDepth': '$subtreeDepth',
+    };
+
+    return parseDiagnosticsNodeDaemon(invokeServiceMethodDaemonParams(
+      getDetailsSubtreeWithRenderObjectServiceExtensionName,
+      args,
+    ));
   }
 }