- Install
- Set up an editor
- Test drive
- Write your first Flutter app, part 1
- Learn more
- Flutter for Android developers
- Flutter for iOS developers
- Flutter for React Native developers
- Flutter for web developers
- Flutter for Xamarin.Forms developers
- Introduction to declarative UI
- Cookbook
- Codelabs
- Tutorials
- User interface
- Introduction to widgets
- Layouts in Flutter
- Layout tutorial
- Dealing with box constraints
- Adding interactivity to your Flutter app
- Adding assets and images
- Navigation & routing
- Introduction to animations
- Animations overview
- Animations tutorial
- Hero Animations
- Staggered Animations
- Advanced UI
- Slivers
- Taps, drags, and other gestures
- Widget catalog
- Data & backend
- State management
- State management
- Start thinking declaratively
- Differentiate between ephemeral state and app state
- Simple app state management
- List of state management approaches
- JSON and serialization
- Firebase
- Accessibility & internationalization
- Accessibility
- Internationalizing Flutter apps
- Platform integration
- Writing custom platform-specific code
- Packages & plugins
- Using packages
- Developing packages & plugins
- Background processes
- Tools & techniques
- Android Studio / IntelliJ
- Visual Studio Code
- Upgrading Flutter
- Hot reload
- Code formatting
- Debugging Flutter apps
- Using OEM debuggers
- Flutter's build modes
- Testing Flutter apps
- Performance best practices
- Flutter performance profiling
- Creating flavors for Flutter
- Preparing an Android App for Release
- Preparing an iOS App for Release
- Continuous Delivery using fastlane with Flutter
- Bootstrap into Dart
- Inside Flutter
- Platform specific behaviors and adaptations
- Technical Overview
- Technical videos
- FAQ
- Flutter widget index
- Install
- Windows install
- MacOS install
- Linux install
- Set up an editor
- Write your first Flutter app, part 1
- Learn more
- Cupertino (iOS-style) widgets
- Layout widgets
- Animation and motion widgets
- Retrieve the value of a text field
- Basic widgets
- Material Components widgets
- Animate the properties of a Container
- Fade a Widget in and out
- Add a Drawer to a screen
- Displaying SnackBars
- Exporting fonts from a package
- Updating the UI based on orientation
- Using Themes to share colors and font styles
- Using custom fonts
- Working with Tabs
- Building a form with validation
- Create and style a text field
- Focus on a Text Field
- Handling changes to a text field
- Retrieve the value of a text field
- Adding Material Touch Ripples
- Handling Taps
- Implement Swipe to Dismiss
- Display images from the internet
- Fade in images with a placeholder
- Working with cached images
- Basic List
- Create a horizontal list
- Creating a Grid List
- Creating lists with different types of items
- Place a floating app bar above a list
- Working with long lists
- Report errors to a service
- Animating a Widget across screens
- Navigate to a new screen and back
- Navigate with named routes
- Pass arguments to a named route
- Return data from a screen
- Send data to a new screen
- Fetch data from the internet
- Making authenticated requests
- Parsing JSON in the background
- Working with WebSockets
- Persist data with SQLite
- Reading and Writing Files
- Storing key-value data on disk
- Play and pause a video
- Take a picture using the Camera
- An introduction to integration testing
- Performance profiling
- Scrolling
- An introduction to unit testing
- Mock dependencies using Mockito
- An introduction to widget testing
- Finding widgets
- Tapping, dragging and entering text
- Development
- Introduction to widgets
- Layout tutorial
- Dealing with box constraints
- Adding interactivity to your Flutter app
- Adding assets and images
- Navigation & routing
- Navigate to a new screen and back
- Send data to a new screen
- Return data from a screen
- Navigate with named routes
- Animating a Widget across screens
- AnimatedList
- Sample App Catalog
- Animations overview
- Animations tutorial
- Staggered Animations
- Slivers
- Taps, drags, and other gestures
- Accessibility widgets
- Assets, images, and icon widgets
- Async widgets
- Input widgets
- Interaction model widgets
- Painting and effect widgets
- Scrolling widgets
- Styling widgets
- Text widgets
- State management
- Start thinking declaratively
- Differentiate between ephemeral state and app state
- Simple app state management
- List of state management approaches
- JSON and serialization
- Accessibility
- Internationalizing Flutter apps
- Writing custom platform-specific code
- Using packages
- Fetch data from the internet
- Developing packages & plugins
- Background processes
- Android Studio / IntelliJ
- Set up an editor
- Flutter inspector
- Creating Useful Bug Reports
- Visual Studio Code
- Set up an editor
- Upgrading Flutter
- Hot reload
- Code formatting
Hot reload
Flutter’s hot reload feature helps you quickly and easily experiment, build UIs, add features, and fix bugs. Hot reload works by injecting updated source code files into the running Dart Virtual Machine (VM). After the VM updates classes with the new versions of fields and functions, the Flutter framework automatically rebuilds the widget tree, allowing you to quickly view the effects of your changes.
To hot reload a Flutter app:
- Run the app from a supported Flutter editor or a terminal window. Either a physical or virtual device can be the target. Only Flutter apps in debug mode can be hot reloaded.
- Modify one of the Dart files in your project. Most types of code changes can be hot reloaded; for a list of changes that require a hot restart, see Limitations.
If you’re working in an IDE/editor that supports Flutter’s IDE tools, select Save All (
cmd-s
/ctrl-s
), or click the Hot Reload button on the toolbar:If you’re running the app at the command line using
flutter run
, enterr
in the terminal window.
After a successful hot reload operation, you’ll see a message in the console similar to:
Performing hot reload...
Reloaded 1 of 448 libraries in 978ms.
The app updates to reflect your change, and the current state of the app—the value of the counter variable in the above example—is preserved. Your app continues to execute from where it was prior to running the hot reload command. The code updates and execution continues.
A code change has a visible effect only if the modified Dart code is run again after the change. Specifically, a hot reload causes all the existing widgets to rebuild. Only code involved in the rebuilding of the widgets are automatically re-executed.
The next sections describe common situations where the modified code will not run again after hot reload. In some cases, small changes to the Dart code will enable you to continue using hot reload for your app.
Compilation errors
When a code change introduces a compilation error, hot reload always generates an error message similar to:
Hot reload was rejected:
'/Users/obiwan/Library/Developer/CoreSimulator/Devices/AC94F0FF-16F7-46C8-B4BF-218B73C547AC/data/Containers/Data/Application/4F72B076-42AD-44A4-A7CF-57D9F93E895E/tmp/ios_testWIDYdS/ios_test/lib/main.dart': warning: line 16 pos 38: unbalanced '{' opens here
Widget build(BuildContext context) {
^
'/Users/obiwan/Library/Developer/CoreSimulator/Devices/AC94F0FF-16F7-46C8-B4BF-218B73C547AC/data/Containers/Data/Application/4F72B076-42AD-44A4-A7CF-57D9F93E895E/tmp/ios_testWIDYdS/ios_test/lib/main.dart': error: line 33 pos 5: unbalanced ')'
);
^
In this situation, simply correct the errors on the specified lines of Dart code to keep using hot reload.
Previous state is combined with new code
Flutter’s hot reload feature, sometimes described as stateful hot reload, preserves the state of your app. This design enables you to view the effect of the most recent change only, without throwing away the current state. For example, if your app requires a user to log in, you can modify and hot reload a page several levels down in the navigation hierarchy, without re-entering your login credentials. State is kept, which is usually the desired behavior.
If code changes affect the state of your app (or its dependencies), the data your app has to work with might not be fully consistent with the data it would have if it executed from scratch. The result might be different behavior after hot reload versus a hot restart.
For example, if you modify a class definition from extending StatelessWidget to StatefulWidget (or the reverse), after hot reload the previous state of your app is preserved. However, the state might not be compatible with the new changes.
Consider the following code:
class MyWidget extends StatelessWidget {
Widget build(BuildContext context) {
return GestureDetector(onTap: () => print('T'));
}
}
After running the app, if you make the following change:
class MyWidget extends StatefulWidget {
@override
State<MyWidget> createState() => MyWidgetState();
}
class MyWidgetState extends State<MyWidget> { /*...*/ }
Then hot reload; the console displays an assertion failure similar to:
MyWidget is not a subtype of StatelessWidget
In these situations, a hot restart is required to see the updated app.
Recent code change is included but app state is excluded
In Dart, static fields are lazily initialized. This means that the first time you run a Flutter app and a static field is read, it is set to whatever value its initializer was evaluated to. Global variables and static fields are treated as state, and are therefore not reinitialized during hot reload.
If you change initializers of global variables and static fields, a full restart is necessary to see the changes. For example, consider the following code:
final sampleTable = [
Table("T1"),
Table("T2"),
Table("T3"),
Table("T4"),
];
After running the app, if you make the following change:
final sampleTable = [
Table("T1"),
Table("T2"),
Table("T3"),
Table("T10"), // modified
];
and then hot reload, the change is not reflected.
Conversely, in the following example:
const foo = 1;
final bar = foo;
void onClick() {
print(foo);
print(bar);
}
running the app for the first time prints 1
and 1
. Then, if you make the following change:
const foo = 2; // modified
final bar = foo;
void onClick() {
print(foo);
print(bar);
}
and hot reload, it now prints 2
and 1
. While changes to const
field values are always hot reloaded, the static field initializer is not rerun. Conceptually, const
fields are treated like aliases instead of state.
The Dart VM detects initializer changes and flags when a set of changes needs a hot restart to take effect. The flagging mechanism is triggered for most of the initialization work in the above example, but not for cases like:
final bar = foo;
To be able to update foo
and view the change after hot reload, consider redefining the field as const
or using a getter to return the value, rather than using final
. For example:
const bar = foo;
or:
get bar => foo;
Read more about the differences between the const
and final
keywords in Dart.
Recent UI change is excluded
Even when a hot reload operation appears successful and generates no exceptions, some code changes might not be visible in the refreshed UI. This behavior is common after changes to the app’s main()
method.
As a general rule, if the modified code is downstream of the root widget’s build method, then hot reload behaves as expected. However, if the modified code won’t be re-executed as a result of rebuilding the widget tree, then you won’t see its effects after hot reload.
For example, consider the following code:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return GestureDetector(onTap: () => print('tapped'));
}
}
After running this app, you might change the code as follows:
import 'package:flutter/widgets.dart';
void main() {
runApp(const Center(
child: const Text('Hello', textDirection: TextDirection.ltr)));
}
With a hot restart, the program starts from the beginning, executes the new version of main()
, and builds a widget tree that displays the text Hello
.
However, if you hot reload the app after this change, main()
is not re-executed, and the widget tree is rebuilt with the unchanged instance of MyApp
as the root widget. The result is no visible change after hot reload.
Limitations
You might also encounter the rare cases where hot reload is not supported at all. These include:
Enumerated types are changed to regular classes or regular classes are changed to enumerated types. For example, if you change:
enum Color { red, green, blue }
to:
class Color { Color(this.i, this.j); final int i; final int j; }
Generic type declarations are modified. For example, if you change:
class A<T> { T i; }
to:
class A<T, V> { T i; V v; }
In these situations, hot reload generates a diagnostic message and fails without committing any changes.
How it works
When hot reload is invoked, the host machine looks at the edited code since the last compilation. The following libraries are recompiled:
- Any libraries with changed code.
- The application’s main library.
- The libraries from the main library leading to affected libraries.
In Dart 2, those libraries’ Dart source code are turned into kernel files and sent to the mobile device’s Dart VM.
The Dart VM re-loads all libraries from the new kernel file. So far no code is re-executed.
The hot reload mechanism then causes the Flutter framework to trigger a rebuild/re-layout/repaint of all existing widgets and render objects.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论