Repository navigation
runZoned with zoneValues lost after hot reload #93676
Copy link
Copy link
Closed
Labels
P3Issues that are less important to the Flutter projectIssues that are less important to the Flutter projectblockedIssue is blocked by another issueIssue is blocked by another issuec: new featureNothing broken; request for a new capabilityNothing broken; request for a new capabilitycustomer: crowdAffects or could affect many people, though not necessarily a specific customer.Affects or could affect many people, though not necessarily a specific customer.dependency: dartDart team may need to help usDart team may need to help usfound in release: 2.5Found to occur in 2.5Found to occur in 2.5found in release: 2.6Found to occur in 2.6Found to occur in 2.6found in release: 2.8Found to occur in 2.8Found to occur in 2.8frameworkflutter/packages/flutter repository. See also f: labels.flutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer versionIssue is closed as already fixed in a newer versiont: hot reloadReloading code during "flutter run"Reloading code during "flutter run"team-frameworkOwned by Framework teamOwned by Framework teamtoolAffects the "flutter" command-line tool. See also t: labels.Affects the "flutter" command-line tool. See also t: labels.triaged-frameworkTriaged by Framework teamTriaged by Framework team
Description
Steps to Reproduce
- Run the following DartPad
- Note that the zoneValue, 'Hello World' is consistently accessible even across rebuilds (tapping increment)
- Copy the same code and run on mobile (iOS or Android) via
flutter run - Note that the zoneValue, 'Hello World' is consistently accessible even across rebuilds (tapping increment)
- Trigger a Hot Reload
- Note that the zoneValue 'Hello World' is no longer accessible.
- Tap the increment button or Trigger a Hot Restart
- Note that the zoneValue, 'Hello World' is again accessible.
Expected results:
I would expect zoneValues to be accessible across hot reloads.
Actual results:
zoneValues are lost after a hot reload until either a hot restart or a widget rebuild.
Additional Context
If we make token const it doesn't appear to have an impact.
Also, if we define a class MyModel:
class MyModel {
final value = Zone.current[token] as String?;
}And instantiate MyModel within the State:
import 'dart:async';
import 'package:flutter/material.dart';
const token = '__token__';
void main() {
runZoned(
() => runApp(const MyApp()),
zoneValues: {token: 'Hello World'},
);
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
final _myModel = MyModel();
@override
Widget build(BuildContext context) {
final zone = Zone.current;
final value = zone[token] as String?;
return Scaffold(
appBar: AppBar(title: const Text('Zones Demo')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
Text('Zone HashCode: ${zone.hashCode}'),
Text('Zone Value: $value'),
Text('Model Value: ${_myModel.value}'),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => setState(() => _counter++),
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
class MyModel {
final value = Zone.current[token] as String?;
}Then the value retrieved from the model behaves as expected even across hot reloads.
It looks like the current zone is not copied during a hot reload.
Code sample
import 'dart:async';
import 'package:flutter/material.dart';
final token = Object();
void main() {
runZoned(
() => runApp(const MyApp()),
zoneValues: {token: 'Hello World'},
);
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
@override
Widget build(BuildContext context) {
final zone = Zone.current;
final value = zone[token] as String?;
return Scaffold(
appBar: AppBar(title: const Text('Zones Demo')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
Text('Zone HashCode: ${zone.hashCode}'),
Text('Zone Value: $value'),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => setState(() => _counter++),
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}Logs
{"CFBundleName":"zones","DTXcode":"1310","DTSDKName":"iphonesimulator15.0","UILaunchStoryboardName":"LaunchScreen","CFBundleIcons~ipad":{"CFBundlePrimaryIcon":{"CFBundleIconFiles":["AppIcon20x20","AppIcon29x29","AppIcon40x40","AppIcon60x60","AppIcon76x76","AppIcon83.5x83.
5"],"CFBundleIconName":"AppIcon"}},"DTSDKBuild":"19A339","CFBundleDevelopmentRegion":"en","CFBundleVersion":"1","BuildMachineOSBuild":"21A559","DTPlatformName":"iphonesimulator","CFBundlePackageType":"APPL","UIMainStoryboardFile":"Main","CFBundleSupportedPlatforms":["iPho
neSimulator"],"CFBundleShortVersionString":"1.0.0","CFBundleInfoDictionaryVersion":"6.0","CFBundleExecutable":"Runner","DTCompiler":"com.apple.compilers.llvm.clang.1_0","UISupportedInterfaceOrientations~ipad":["UIInterfaceOrientationPortrait","UIInterfaceOrientationPortra
itUpsideDown","UIInterfaceOrientationLandscapeLeft","UIInterfaceOrientationLandscapeRight"],"MinimumOSVersion":"9.0","CFBundleIdentifier":"com.example.zones","UIDeviceFamily":[1,2],"DTPlatformVersion":"15.0","CFBundleSignature":"????","CFBundleIcons":{"CFBundlePrimaryIcon
":{"CFBundleIconFiles":["AppIcon20x20","AppIcon29x29","AppIcon40x40","AppIcon60x60"],"CFBundleIconName":"AppIcon"}},"DTXcodeBuild":"13A1030d","LSRequiresIPhoneOS":true,"UISupportedInterfaceOrientations":["UIInterfaceOrientationPortrait","UIInterfaceOrientationLandscapeLef
t","UIInterfaceOrientationLandscapeRight"],"UIViewControllerBasedStatusBarAppearance":false,"NSBonjourServices":["_dartobservatory._tcp"],"DTPlatformBuild":"19A339","NSLocalNetworkUsageDescription":"Allow Flutter tools on your computer to connect and debug your
application. This prompt will not appear on release builds."}
[ +4 ms] executing: xcrun simctl launch FCB4BE3E-33DA-49FC-A861-F647555D56A9 com.example.zones --enable-dart-profiling --enable-checked-mode --verify-entry-points --observatory-port=0
[ +205 ms] com.example.zones: 51465
[ +1 ms] Waiting for observatory port to be available...
[ +416 ms] Observatory URL on device: http://127.0.0.1:55348/QIoVQ24XVz0=/
[ +9 ms] Caching compiled dill
[ +51 ms] Connecting to service protocol: http://127.0.0.1:55348/QIoVQ24XVz0=/
[ +167 ms] Launching a Dart Developer Service (DDS) instance at http://127.0.0.1:0, connecting to VM service at http://127.0.0.1:55348/QIoVQ24XVz0=/.
[ +95 ms] DDS is listening at http://127.0.0.1:55351/1RcuH9jFcOE=/.
[ +59 ms] Successfully connected to service protocol: http://127.0.0.1:55348/QIoVQ24XVz0=/
[ +26 ms] DevFS: Creating new filesystem on the device (null)
[ +17 ms] DevFS: Created new filesystem on the device (file:///Users/felix/Library/Developer/CoreSimulator/Devices/FCB4BE3E-33DA-49FC-A861-F647555D56A9/data/Containers/Data/Application/42BE9414-534D-477C-ADEB-EDC73F58B7FA/tmp/zonesEyB4Fm/zones/)
[ +2 ms] Updating assets
[ +63 ms] Syncing files to device iPhone 13...
[ +2 ms] <- reset
[ ] Compiling dart to kernel with 0 updated files
[ +3 ms] <- recompile package:zones/main.dart 7fd16ad6-36b9-4ac5-99dd-f42726cef603
[ ] <- 7fd16ad6-36b9-4ac5-99dd-f42726cef603
[ +64 ms] Updating files.
[ ] DevFS: Sync finished
[ ] Syncing files to device iPhone 13... (completed in 71ms)
[ ] Synced 0.0MB.
[ +1 ms] <- accept
[ +6 ms] Connected to _flutterView/0x7fb30a810c20.
[ +3 ms] Flutter run key commands.
[ +1 ms] r Hot reload. 🔥🔥🔥
[ ] R Hot restart.
[ ] h List all available interactive commands.
[ ] d Detach (terminate "flutter run" but leave application running).
[ ] c Clear the screen
[ ] q Quit (terminate the application on the device).
[ ] 💪 Running with sound null safety 💪
[ ] An Observatory debugger and profiler on iPhone 13 is available at: http://127.0.0.1:55351/1RcuH9jFcOE=/
[ +490 ms] The Flutter DevTools debugger and profiler on iPhone 13 is available at: http://127.0.0.1:9102?uri=http://127.0.0.1:55351/1RcuH9jFcOE=/
[+4486 ms] Skipping target: gen_localizations
[ ] Skipping target: gen_dart_plugin_registrant
[ ] Skipping target: _composite
[ ] complete
[ ] Performing hot reload...
[ +11 ms] Scanned through 528 files in 6ms
[ ] Syncing files to device iPhone 13...
[ ] Compiling dart to kernel with 0 updated files
[ ] <- recompile package:zones/main.dart 564d0ee5-dbd9-4020-bfeb-4217c387483f
[ ] <- 564d0ee5-dbd9-4020-bfeb-4217c387483f
[ +6 ms] Updating files.
[ +2 ms] DevFS: Sync finished
[ ] Syncing files to device iPhone 13... (completed in 9ms)
[ ] Synced 0.0MB.
[ +11 ms] Reassembling application
[ +39 ms] Hot reload performed in 67ms.
[ +1 ms] Performing hot reload... (completed in 73ms)
[ ] Reloaded 0 libraries in 78ms.
No issues found! (ran in 1.9s)
[✓] Flutter (Channel beta, 2.7.0-3.1.pre, on macOS 12.0.1 21A559 darwin-x64, locale en-US)
• Flutter version 2.7.0-3.1.pre at /Users/felix/fvm/versions/beta
• Upstream repository [email protected]:flutter/flutter.git
• Framework revision fc7015e35a (3 weeks ago), 2021-10-27 15:18:41 -0700
• Engine revision a75e3b80f9
• Dart version 2.15.0 (build 2.15.0-178.1.beta)
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
• Android SDK at /Users/felix/Library/Android/sdk
• Platform android-30, build-tools 29.0.2
• Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 13.1)
• Xcode at /Applications/Xcode.app/Contents/Developer
• CocoaPods version 1.11.2
[✓] Chrome - develop for the web
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Android Studio (version 4.1)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
• Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)
[✓] IntelliJ IDEA Community Edition (version 2021.2)
• IntelliJ at /Applications/IntelliJ IDEA CE.app
• Flutter plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/9212-flutter
• Dart plugin can be installed from:
🔨 https://plugins.jetbrains.com/plugin/6351-dart
[✓] VS Code (version 1.60.1)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.27.0
[✓] VS Code (version 1.63.0-insider)
• VS Code at /Applications/Visual Studio Code - Insiders.app/Contents
• Flutter extension version 3.28.0
[✓] Connected device (3 available)
• iPhone 13 (mobile) • FCB4BE3E-33DA-49FC-A861-F647555D56A9 • ios • com.apple.CoreSimulator.SimRuntime.iOS-15-0 (simulator)
• macOS (desktop) • macos • darwin-x64 • macOS 12.0.1 21A559 darwin-x64
• Chrome (web) • chrome • web-javascript • Google Chrome 95.0.4638.69
• No issues found!
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
P3Issues that are less important to the Flutter projectIssues that are less important to the Flutter projectblockedIssue is blocked by another issueIssue is blocked by another issuec: new featureNothing broken; request for a new capabilityNothing broken; request for a new capabilitycustomer: crowdAffects or could affect many people, though not necessarily a specific customer.Affects or could affect many people, though not necessarily a specific customer.dependency: dartDart team may need to help usDart team may need to help usfound in release: 2.5Found to occur in 2.5Found to occur in 2.5found in release: 2.6Found to occur in 2.6Found to occur in 2.6found in release: 2.8Found to occur in 2.8Found to occur in 2.8frameworkflutter/packages/flutter repository. See also f: labels.flutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer versionIssue is closed as already fixed in a newer versiont: hot reloadReloading code during "flutter run"Reloading code during "flutter run"team-frameworkOwned by Framework teamOwned by Framework teamtoolAffects the "flutter" command-line tool. See also t: labels.Affects the "flutter" command-line tool. See also t: labels.triaged-frameworkTriaged by Framework teamTriaged by Framework team
Activity
danagbemava-nc commentedon Nov 16, 2021
Reproducible on all channels.
logs
videos
using initial samplescreen.recording.mp4
using sample with MyModel classSimulator.Screen.Recording.-.iPhone.13.-.2021-11-16.at.09.44.20.mp4
flutter doctor -v
christopherfujino commentedon Nov 16, 2021
@rmacnak-google is this a bug or working as intended?
felangel commentedon Nov 23, 2021
Another issue related to this can be seen by adding
WidgetsFlutterBinding.ensureInitialized();and observing that thezoneValuesare no longer available withinonPressedcallbacks.I think I understand why this is happening,
WidgetsFlutterBinding.ensureInitialized();is called within the root zone and it contains theGestureBindingbut is there any way to setup theServicesBindingandSchedulerBindingsto communicate with the platform without initializing the remaining bindings?A use case is wanting to provide a
zoneValuethat comes from the underlying platform. With the current approach thezoneValueis not available inonPressedcallbacks because theWidgetsFlutterBindinginitialization is outside of the zone.EDIT
I opened #94123 regarding the above use-case.
dnfield commentedon Nov 30, 2021
here's a pared down example of what's happening:
If you uncomment the commented lines, things work as expected. The problem is we're running the reassmble callback in the root zone no matter what.
17 remaining items
Hixie commentedon Dec 5, 2022
Yeah, I believe that's what we do for most other engine callback entry points. I haven't tested that it would solve the issue here, but it should, I think?
brianquinlan commentedon Dec 14, 2022
Empirically, hot reload works with
package:http, which usesbindCallbackRun extension handlers in the registering zone
mkustermann commentedon Aug 11, 2023
@Hixie wasn't this fixed in dart-lang/sdk@ca03588 (which refers to this issue)?
[vm] Add test for `dart:developer` `registerExtension()` method
Hixie commentedon Aug 11, 2023
Apparently, and then we never closed this one! Oops! Thanks for the information!
github-actions commentedon Aug 28, 2023
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.