Flutter)应用程序在热重载前不处理
Flutter) App doesn't dispose before hot reloading
我现在在研究flutter。但是我遇到了一个关于 dispose 的问题。
首先我给你看我的代码。看起来很长,但不是难码。
main.dart
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: FirstScreen(),
);
}
}
class FirstScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// After hot reload, title will be changed to 'First Screen (After Hot Reload)'
title: Text('First Screen (Before Hot Reload)', style: TextStyle(fontWeight: FontWeight.bold)),
),
body: SafeArea(
child: Center(
child: ElevatedButton(
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (_) => SecondScreen()));
},
child: Text('Go To Second Screen', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 24)),
),
),
),
);
}
}
class SecondScreen extends StatefulWidget {
@override
_SecondScreenState createState() => _SecondScreenState();
}
class _SecondScreenState extends State<SecondScreen> with TickerProviderStateMixin {
List<ScrollController> scrollControllers;
List<AnimationController> animationControllers;
List<FocusNode> focusNodes;
@override
void initState() {
super.initState();
scrollControllers = List.generate(10000, (_) => ScrollController());
animationControllers = List.generate(10000, (_) => AnimationController(vsync: this, duration: Duration(microseconds: 300)));
focusNodes = List.generate(10000, (_) => FocusNode());
}
@override
void dispose() {
scrollControllers.forEach((element) { element.dispose();});
animationControllers.forEach((element) { element.dispose();});
focusNodes.forEach((element) { element.dispose();});
print('No Get with dispose');
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// After hot reload, title will be changed to 'Second Screen (After Hot Reload)'
title: Text('Second Screen (Before Hot Reload)', style: TextStyle(fontWeight: FontWeight.bold)),
),
body: SafeArea(
child: Center(child: Text('Second Screen')),
),
);
}
}
我构建这段代码并观察这个简单应用程序的内存使用情况。
My app memory usage
我运行这个应用有这个步骤。
- 我 运行 具有调试模式的应用程序。
- 我转到第二个屏幕。 (然后,此应用程序将在 initState() 方法中创建 10,000 个
ScrollController
、AnimationController
和 FocusNode
)
- 我回到第一屏。 (我认为这个应用程序应该在 dispose() 方法中处理
ScrollController
、AnimationController
和 FocusNode
。但它没有。)
- 我很少更改代码。只是 AppBar 的标题文本。并重新加载。然后,和app开头类似,内存占用发生了变化。
- 我转到第二个屏幕。它创建类似于步骤 2 的内容。
- 我回到第一屏。此时,它正确处理了。
问题
这是我的问题。为什么此应用程序在第 3 步不处理 scrollControllers
、animationConrollers
、focusNodes
?但是,在热重载后,此应用程序在 returns 到第一个屏幕时会正确处理(第 6 步)。这对我来说很奇怪。为什么一开始构建应用程序不处理,但在热重载应用程序后正确处理?
p.s.) 我用的是 IntelliJ.
'flutter --version' 结果
Flutter 1.22.5 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 7891006299 (7 weeks ago) • 2020-12-10 11:54:40 -0800
Engine • revision ae90085a84
Tools • Dart 2.10.4
'flutter doctor' 结果
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 1.22.5, on Microsoft Windows [Version 10.0.19042.746], locale ko-KR)
[!] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
✗ Android license status unknown.
Run `flutter doctor --android-licenses` to accept the SDK licenses.
See https://flutter.dev/docs/get-started/install/windows#android-setup for more details.
[!] Android Studio (not installed)
[!] VS Code (version 1.52.1)
✗ Flutter extension not installed; install from
https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter
[✓] Connected device (1 available)
如果您的任务需要在热重载时进行特殊处理,您可以提供一个 reassemble
挂钩(类似于处理)来运行您需要的代码:
// in your State widget:
@override
void reassemble {
debugPrint('Captain, we are going down!!!');
super.reassemble(); // must call
}
在 https://api.flutter.dev/flutter/widgets/State/reassemble.html 查看更多信息。
文档说这仅适用于调试版本,因为当然,您不能在生产版本上热重新加载。 :)
我现在在研究flutter。但是我遇到了一个关于 dispose 的问题。
首先我给你看我的代码。看起来很长,但不是难码。
main.dart
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: FirstScreen(),
);
}
}
class FirstScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// After hot reload, title will be changed to 'First Screen (After Hot Reload)'
title: Text('First Screen (Before Hot Reload)', style: TextStyle(fontWeight: FontWeight.bold)),
),
body: SafeArea(
child: Center(
child: ElevatedButton(
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (_) => SecondScreen()));
},
child: Text('Go To Second Screen', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 24)),
),
),
),
);
}
}
class SecondScreen extends StatefulWidget {
@override
_SecondScreenState createState() => _SecondScreenState();
}
class _SecondScreenState extends State<SecondScreen> with TickerProviderStateMixin {
List<ScrollController> scrollControllers;
List<AnimationController> animationControllers;
List<FocusNode> focusNodes;
@override
void initState() {
super.initState();
scrollControllers = List.generate(10000, (_) => ScrollController());
animationControllers = List.generate(10000, (_) => AnimationController(vsync: this, duration: Duration(microseconds: 300)));
focusNodes = List.generate(10000, (_) => FocusNode());
}
@override
void dispose() {
scrollControllers.forEach((element) { element.dispose();});
animationControllers.forEach((element) { element.dispose();});
focusNodes.forEach((element) { element.dispose();});
print('No Get with dispose');
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// After hot reload, title will be changed to 'Second Screen (After Hot Reload)'
title: Text('Second Screen (Before Hot Reload)', style: TextStyle(fontWeight: FontWeight.bold)),
),
body: SafeArea(
child: Center(child: Text('Second Screen')),
),
);
}
}
我构建这段代码并观察这个简单应用程序的内存使用情况。
My app memory usage
我运行这个应用有这个步骤。
- 我 运行 具有调试模式的应用程序。
- 我转到第二个屏幕。 (然后,此应用程序将在 initState() 方法中创建 10,000 个
ScrollController
、AnimationController
和FocusNode
) - 我回到第一屏。 (我认为这个应用程序应该在 dispose() 方法中处理
ScrollController
、AnimationController
和FocusNode
。但它没有。) - 我很少更改代码。只是 AppBar 的标题文本。并重新加载。然后,和app开头类似,内存占用发生了变化。
- 我转到第二个屏幕。它创建类似于步骤 2 的内容。
- 我回到第一屏。此时,它正确处理了。
问题
这是我的问题。为什么此应用程序在第 3 步不处理 scrollControllers
、animationConrollers
、focusNodes
?但是,在热重载后,此应用程序在 returns 到第一个屏幕时会正确处理(第 6 步)。这对我来说很奇怪。为什么一开始构建应用程序不处理,但在热重载应用程序后正确处理?
p.s.) 我用的是 IntelliJ.
'flutter --version' 结果
Flutter 1.22.5 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 7891006299 (7 weeks ago) • 2020-12-10 11:54:40 -0800
Engine • revision ae90085a84
Tools • Dart 2.10.4
'flutter doctor' 结果
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 1.22.5, on Microsoft Windows [Version 10.0.19042.746], locale ko-KR)
[!] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
✗ Android license status unknown.
Run `flutter doctor --android-licenses` to accept the SDK licenses.
See https://flutter.dev/docs/get-started/install/windows#android-setup for more details.
[!] Android Studio (not installed)
[!] VS Code (version 1.52.1)
✗ Flutter extension not installed; install from
https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter
[✓] Connected device (1 available)
如果您的任务需要在热重载时进行特殊处理,您可以提供一个 reassemble
挂钩(类似于处理)来运行您需要的代码:
// in your State widget:
@override
void reassemble {
debugPrint('Captain, we are going down!!!');
super.reassemble(); // must call
}
在 https://api.flutter.dev/flutter/widgets/State/reassemble.html 查看更多信息。 文档说这仅适用于调试版本,因为当然,您不能在生产版本上热重新加载。 :)