flutter / flutter-intellij

Flutter Plugin for IntelliJ
https://flutter.dev/using-ide
BSD 3-Clause "New" or "Revised" License
1.98k stars 319 forks source link

Web app is built twice after every hot restart if any event happens #5870

Open krisztianodor opened 2 years ago

krisztianodor commented 2 years ago

Steps to Reproduce

  1. Let's say that i have a simple stateful MyApp widget with a MaterialApp widget inside (the sample code is below).
  2. When I first run the app on the web (Chrome browser) everything is okay: the initState and the build method is called once
  3. Then i save without any change, which triggers a hot restart and it seems that everything is okay: the initState and the build method is called again and only once
  4. Now if i do something on the site (button hover or window resize, etc), then the build method is called again once. The question is why? It should no be called.

This is the output of the Intellij console after step 3:

Performing hot restart...
Waiting for connection from debug service on Chrome...
Restarted application in 2,556ms.
MyApp initState called
MyApp build called
MyApp build called

Complete code to reproduce the problem:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  void initState() {
    super.initState();
    print('MyApp initState called');
  }

  @override
  Widget build(BuildContext context) {
    print('MyApp build called');
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Welcome to Flutter'),
        ),
        body: Center(
          child: OutlinedButton(
            onPressed: () {},
            child: const Text('Button'),
          ),
        ),
      ),
    );
  }
}

By the way if i run the app directly using the flutter cli (outside Intellij) with the following command and i hit 'r' to trigger a hot restart, then the hot restart is waiting and executed only if the focus is on the browser. And there are no unnecessary builds in the hot restart instance even if i do something on the site. I don't think that's a coincidence.

flutter run -d chrome

Version info

/Users/.../development/flutter/bin/flutter doctor --verbose
[✓] Flutter (Channel stable, 2.5.3, on macOS 12.0.1 21A559 darwin-x64, locale en-HU)
    • Flutter version 2.5.3 at /Users/.../development/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 18116933e7 (6 weeks ago), 2021-10-15 10:46:35 -0700
    • Engine revision d3ea636dc5
    • Dart version 2.14.4

[!] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
    • Android SDK at /Users/.../Library/Android/sdk
    ✗ cmdline-tools component is missing
      Run `path/to/sdkmanager --install "cmdline-tools;latest"`
      See https://developer.android.com/studio/command-line for more details.
    ✗ Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.

[!] Xcode - develop for iOS and macOS
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 13.1, Build version 13A1030d
    ! CocoaPods 1.9.3 out of date (1.10.0 is recommended).
        CocoaPods is used to retrieve the iOS and macOS platform side's plugin code that responds to your plugin usage on the Dart side.
        Without CocoaPods, plugins will not work on iOS or macOS.
        For more info, see https://flutter.dev/platform-plugins
      To upgrade see https://guides.cocoapods.org/using/getting-started.html#installation for instructions.

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 4.0)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin version 50.0.1
    • Dart plugin version 193.7547
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6222593)

[✓] IntelliJ IDEA Ultimate Edition (version 2021.2.2)
    • IntelliJ at /Applications/IntelliJ IDEA.app
    • Flutter plugin version 61.2.4
    • Dart plugin version 212.5632

[✓] Connected device (1 available)
    • Chrome (web) • chrome • web-javascript • Google Chrome 96.0.4664.55

! Doctor found issues in 2 categories.
Process finished with exit code 0

I can reproduce this problem at flutter stable, dev and master channel too.

stevemessick commented 2 years ago

Thanks for the repro code, that's very helpful.

I can reproduce this issue. I think it has something to do with how the app runs when started with the --machine option (which IDEs use to enable control of the app).

This isn't specific to web apps. I saw the same thing when running the app in an Android emulator. I had verbose logging on, but the same print statements ran:

[ +333 ms] Hot restart performed in 1,180ms.
[   +1 ms] Restarted application in 1,198ms.
[ +309 ms] I/flutter (18510): MyApp initState called
[   +9 ms] I/flutter (18510): MyApp build called
[+24477 ms] I/flutter (18510): MyApp build called

The second build was triggered when the mouse entered the frame of the emulator.

@DanTup have you observed anything similar with VS Code?

DanTup commented 2 years ago

I don't seem to be able to repro this with VS Code, although it's a little similar to https://github.com/Dart-Code/Dart-Code/issues/3498 where additional builds were happening that was caused by VS Code calling service extension toggles (it was sending them after a restart even if they had not been changed from the default values).

stevemessick commented 2 years ago

Thanks, that's interesting. It could be service extension calls. I think I saw a bunch of them in the log. It isn't obvious why that would trigger a build, though.

DanTup commented 2 years ago

If you enable something like painting overlays I assume it needs to rebuild. I figured maybe it was always triggering the rebuild even if the value didn't really change (which perhaps could be optimised in Flutter if that is the case, but it seemed needless to send them so I changed that in VS Code anyway).

akarabach commented 2 years ago

Any updates on it? Looks like idea calls for flutter web initState twice in my case

devnta commented 11 months ago

It's not happen only on Web, it's still on Android.

iosif-bancioiu commented 7 months ago

Any updates on this? The issue seems to be still here

iosif-bancioiu commented 7 months ago

@jwren do you have any opinion on this? https://github.com/flutter/flutter-intellij/issues/7286 might have the same root cause

Thanks!