Flutter Outline, Hot Reload, and the implementation of a live widget preview

Konstantin Scheglov
Apr 4, 2018 · 4 min read

In M22 of the Flutter plugin for IntelliJ we added a new tool window — the Flutter Outline view. It shows you the structure of your Dart files — the classes, fields, and methods — just like the standard IntelliJ Structure tool window. But when the selected file contains Flutter UI code, it also shows the widget hierarchy — the association between parent and child widgets:

Image for post
Image for post

What’s new?

Now with M23, we’ve introduced a new experimental feature — a live, in-IntelliJ rendering of the widget under development. This can be enabled from the Flutter preferences page in IntelliJ:

Image for post
Image for post

In order for this to work for a widget, the widget class must define a forDesignTime() constructor. The reason for this is that widgets are usually created with context specific constructor parameters. When rendering the preview of the widget, we don’t necessarily know the right values for these parameters. So, we let the user provide them for us via this specially named constructor.

We’ve had several comments that Flutter UI code can be quite long and it can be difficult to construct a mental model and navigate while coding. We realized that a visual presentation and two-way synchronization between the code and its visual presentation could help to solve both problems.

The code for a previewable widget might then look like this:

and its preview would look something like this:

Image for post
Image for post

When trying this out, you’ll note that the preview area will show you the layout of any number of different kinds of widgets (constructible using a forDesignTime() constructor), and will update automatically as you type.

How does it work?

The live preview view ties together technology from hot reload, Flutter’s headless testing binary, and Dart’s analysis server, with an implementation in IntelliJ.

When you open a Dart file in IntelliJ, the Flutter plugin subscribes to Flutter Outline events from the Dart Analysis Server. Every time a file changes, a new ‘Flutter Outline’ event is sent to IntelliJ with structured information about the contents of a file. This information includes classes, methods, fields, as well as information about the Flutter widgets created in the file. Flutter items are created for every instantiation of a Widget subclass and any reference to a Widget typed variable or a method invocation.

In order to map runtime widget instances back to the locations in source where they were created, we re-write the user’s source code to assign a unique ID to each created widget. You can see the instrumented code here:

This instrumented code also comes back as part of the analysis server’s response.

This information is used to populate the tree portion of the outline view. As the user changes selection in the file, we request a re-rendering of the widget preview using the currently selected widget.

We use a standard Flutter tool, which allows headless execution of Flutter code — the flutter_tester binary. You can think about it as part of Dart VM with the dart:ui library and Skia bindings, just like on a mobile device, but on your desktop. We write two files into a temporary directory — the instrumented code itself, and the rendering server. The rendering server listens on stdin for the render command, instantiates the widget to render, puts it into a MaterialApp, grabs positioning information for each widget, and returns JSON information back to the client, with the bounds information mapped to corresponding widget identifiers.

But running a new flutter_tester instance for each cycle would be too slow — it takes about 1000 ms for the Dart VM to start and the JIT to run. So, instead of running a new process each time, we use yet another amazing feature of Flutter and Dart — hot reload. We update the rendering server file to use the new preview area size, the new widget class name to instantiate, and of course write newly instrumented code into the file to render. Then we ask the Dart VM to hot reload the entry point (the rendering server in our case), and it picks up all changes. The whole process takes only about 100 ms, which is 10 times faster than the initial, cold, rendering.

This works well when you switch between files of the same package, because the set of packages stays the same (and we run flutter_tester with this set). But when you switch to a file in another package, we restart the process. We also terminate the process if rendering does not happen fast enough — currently a cutoff of 2000 ms. So, if there is a compilation or a runtime error, once you fix it, eventually the rendering server process will succeed and you will see rendering.

Once the Flutter plugin for IntelliJ gets the outline and corresponding set of bounds for each widget, it paints the widget layout in the preview area using standard Swing components. This preview lets you select a widget outline and see the corresponding entry in the tree view and in the source code.

Kicking the tires

So, go to the preferences panel, turn on live preview, and let us know what you think! We hope it helps you edit and understand your Flutter code and UIs.

Flutter

Flutter is Google's mobile UI framework for crafting…

Konstantin Scheglov

Written by

Software Engineer @ Google

Flutter

Flutter

Flutter is Google's mobile UI framework for crafting high-quality native interfaces on iOS and Android in record time. Flutter works with existing code, is used by developers and organizations around the world, and is free and open source. Learn more at https://flutter.dev

Konstantin Scheglov

Written by

Software Engineer @ Google

Flutter

Flutter

Flutter is Google's mobile UI framework for crafting high-quality native interfaces on iOS and Android in record time. Flutter works with existing code, is used by developers and organizations around the world, and is free and open source. Learn more at https://flutter.dev

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store