Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
143 views
in Technique[技术] by (71.8m points)

android - Flutter) App doesn't dispose before hot reloading

I study flutter nowadays. But I met one problem about dispose.

First I see you my code. It seems long, but it is not difficult code.

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')),
      ),
    );
  }
}

I build this code and watch memory usage of this simple app.

My app memory usage

I run this app with this step.

  1. I run app with debug mode.
  2. I go to second screen. (Then, this app will create 10,000 ScrollController, AnimationController, and FocusNode in initState() method)
  3. I go back to first screen. (I think this app should dispose ScrollController, AnimationController, and FocusNode in dispose() method. But it doesn't.)
  4. I change the code little. Just AppBar's title text. And reload. Then, similar to the beginning of the app, the memory usage has changed.
  5. I go to second screen. It creates things like step 2.
  6. I go back to first screen. At this time, it disposes correctly.

Question Here is my question. Why this app doesn't dispose scrollControllers, animationConrollers, focusNodes at step 3? However, after hot reload this app disposes correctly when it returns to first screen (step 6). It is weird point to me. Why at first build app doesn't dispose, but after hot reload app disposes correctly?


p.s.) I use IntelliJ.

'flutter --version' result

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' result

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)
question from:https://stackoverflow.com/questions/65886437/flutter-app-doesnt-dispose-before-hot-reloading

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If you have tasks that require special handling on a hot reload, you can provide a reassemble hook (similar to dispose) that runs the code you need:

// in your State widget:

@override
void reassemble {
  debugPrint('Captain, we are going down!!!');
  super.reassemble(); // must call
}

See more at https://api.flutter.dev/flutter/widgets/State/reassemble.html. The docs say this works for debug builds only, because of course, you're not hot reloading on a production build. :)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...