Skip to content

Discuss MediaQuery.of in ui.window documentation  #11697

Description

@mzimmerm

Steps to Reproduce

  • Paste the application pasted below inside IntelliJ.
  • Start emulator or attach a physical device
  • Click the Run (>) button to run the app (same issue from flutter run)
  • Both the log and the button shows ui.window.physicalSize=Size(0.0, 0.0)

Note: Terminate the app and Run (>) again a few times if first run does not reproduce.

This does not happen in 100% of tries; in the emulator, almost always. On a physical device (tried Z160) less often.

Logs

Logs from IDE

On first application start, the size is reported incorrectly as (0,0) - both in emulation and physical device.

Launching examples/build_size_bug_on_first_plugin.dart on Android SDK built for x86 in debug mode...
Running 'gradle assembleDebug'...
Built build/app/outputs/apk/app-debug.apk (21.6MB).
I/flutter ( 3819):  ### Size: ui.window.physicalSize=Size(0.0, 0.0), windowLogicalSize=Size(0.0, 0.0),logicalSize=Size(0.0, 0.0)
I/Choreographer( 3819): Skipped 37 frames!  The application may be doing too much work on its main thread.
D/EGL_emulation( 3819): eglMakeCurrent: 0xade85660: ver 2 0 (tinfo 0xade83ed0)
Syncing files to device Android SDK built for x86...

After clicking the + Button, size reported correctly

I/flutter ( 3819):  ### Size: ui.window.physicalSize=Size(768.0, 1184.0), windowLogicalSize=Size(384.0, 592.0),logicalSize=Size(384.0, 296.0)
I/flutter ( 3819):  ### Size: ui.window.physicalSize=Size(768.0, 1184.0), windowLogicalSize=Size(384.0, 592.0),logicalSize=Size(384.0, 296.0)
I/flutter ( 3819):  ### Size: ui.window.physicalSize=Size(768.0, 1184.0), windowLogicalSize=Size(384.0, 592.0),logicalSize=Size(384.0, 296.0)

Also correct after restarting (hitting the Run> button), size reported correctly

Performing full restart...
I/flutter ( 3819):  ### Size: ui.window.physicalSize=Size(768.0, 1184.0), windowLogicalSize=Size(384.0, 592.0),logicalSize=Size(384.0, 296.0)
Restarted app in 1,361ms.

Logs from flutter run

mzimmermann@home-server:~/dev/my-projects-source/public-on-github/flutter_experiments> flutter run examples/build_size_bug_on_first_plugin.dart           
Launching examples/build_size_bug_on_first_plugin.dart on Android SDK built for x86 in debug mode...                                                      
Running 'gradle assembleDebug'...                     1.8s                                                                                                
Built build/app/outputs/apk/app-debug.apk (21.6MB).                                                                                                       
I/flutter ( 3988):  ### Size: ui.window.physicalSize=Size(0.0, 0.0), windowLogicalSize=Size(0.0, 0.0),logicalSize=Size(0.0, 0.0)                          
I/Choreographer( 3988): Skipped 43 frames!  The application may be doing too much work on its main thread.                                                
D/EGL_emulation( 3988): eglMakeCurrent: 0xaab05540: ver 2 0 (tinfo 0xaab03f30)                                                                            
Syncing files to device Android SDK built for x86...  3.5s                                                                                                
                                                                                                                                                          
🔥  To hot reload your app on the fly, press "r". To restart the app entirely, press "R".                                                                 
An Observatory debugger and profiler on Android SDK built for x86 is available at: http://127.0.0.1:8110/                                                 
For a more detailed help message, press "h". To quit, press "q".

Run flutter analyze and attach any output of that command also.

mzimmermann@home-server:~/dev/my-projects-source/public-on-github/flutter_experiments> flutter analyze
Analyzing /home/mzimmermann/dev/my-projects-source/public-on-github/flutter_experiments...
  hint • Unused import at examples/build_size_bug_on_first_plugin.dart:2:8 • unused_import
  hint • Unused import at examples/build_size_bug_on_first_plugin.dart:5:8 • unused_import
2 issues found.
(Ran in 7.2s)

Flutter Doctor

Paste the output of running flutter doctor here.

mzimmermann@home-server:~/dev/my-projects-source/public-on-github/flutter_experiments> flutter doctor
[✓] Flutter (on Linux, locale en_CA.UTF-8, channel alpha)
    • Flutter at /home/mzimmermann/software/flutter/gitclone/flutter
    • Framework revision d36e2f6191 (8 weeks ago), 2017-06-21 15:09:10 -0700
    • Engine revision b0dee695ec
    • Tools Dart version 1.24.0-dev.6.7

[✓] Android toolchain - develop for Android devices (Android SDK 25.0.3)
    • Android SDK at /home/mzimmermann/software/android/studio/sdk
    • Platform android-25, build-tools 25.0.3
    • ANDROID_HOME = /home/mzimmermann/software/android/studio/sdk
    • Java binary at: /home/mzimmermann/software/android/studio/android-studio/jre/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_112-release-b06)

[✓] Android Studio (version 2.3)
    • Android Studio at /home/mzimmermann/software/android/studio/android-studio
    • Gradle version 3.2
    • Java version OpenJDK Runtime Environment (build 1.8.0_112-release-b06)

[✓] IntelliJ IDEA Ultimate Edition (version 2017.2)
    • Flutter plugin version 16.0
    • Dart plugin version 172.3544.10

[✓] Connected devices
    • Android SDK built for x86 • emulator-5554 • android-x86 • Android 7.0 (API 24) (emulator)

The code

I can probably simplify, the only thing that seems to matter is asking for

ui.window.physicalSize
inside build()

import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart' as widgets; // note: external package imp

import 'dart:ui' as ui;
import 'dart:math' as math;

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {

  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo Title',
      debugShowCheckedModeBanner: false,
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {

  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {

  void _stateChanger() {
    this.setState(() { // on State

    });
  }

  @override
  Widget build(BuildContext context) {
    final double devicePixelRatio = ui.window.devicePixelRatio;
    final ui.Size windowLogicalSize = ui.window.physicalSize / devicePixelRatio;
    // Let us give the Painter full width and half of height.
    final ui.Size logicalSize =
    new Size(windowLogicalSize.width, windowLogicalSize.height / 2);

    print(" ### Size: ui.window.physicalSize=${ui.window.physicalSize}, "
        "windowLogicalSize=$windowLogicalSize,"
        "logicalSize=$logicalSize");

    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[

            new Text(
              'size=$logicalSize - this prints (0,0) in first run after device connect.',
            ),
          ],
        ),
      ),
      floatingActionButton: new FloatingActionButton(
        onPressed: _stateChanger,
        tooltip: 'Just force a refresh',
        child: new Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.    );
    );

  }
}

Activity

  1. Hixie commented on Aug 20, 2017

    @Hixie
    Contributor

    This is expected (sometimes by the time the Dart code runs we haven't yet heard from the OS what size the window should be). It happens more in faster builds (e.g. in release mode). Apps are expected to be able to handle being laid out at 0x0.

  2. mzimmerm commented on Aug 20, 2017

    @mzimmerm
    Author

    Ok thanks for the quick response. I will follow up with a question if I may (if something like gitter or stack overflow is a better place please let me know): Are there any guidelines, notes, or documents what apps can do to handle zero size? Especially in case, like I discovered it originally, there is a CustomPainter paint(canvas, size) being passed zero size. canvas is not supposed to be painted beyond size, so the only solution is to return and paint nothing. Ok, but then it will remain so until CustomPainter.paint() is called again (or it the example above the State.build() is called again) - what would be the mechanism for the app to know when the window size is available, and how CustomPainter.paint() be caled again. Thanks

  3. Hixie commented on Aug 20, 2017

    @Hixie
    Contributor

    It should get called automatically when the new size is reported.

  4. Hixie commented on Aug 20, 2017

    @Hixie
    Contributor

    In the sample app above, if you use MediaQuery.of(context) instead of reading straight off ui.window, you should find your app is rebuilt automatically when the size changes.

  5. eseidelGoogle commented on Aug 20, 2017

    @eseidelGoogle
    Contributor

    We've seen this come up before. I wonder if this is a foot-gun that we should somehow change the default behavior of MaterialApp to avoid? Something that folks diving down to the lower layers of our framework can get exposed to, but that we make easy to avoid doing the default thing?

  6. Hixie commented on Aug 20, 2017

    @Hixie
    Contributor

    Which part?

  7. mzimmerm commented on Aug 20, 2017

    @mzimmerm
    Author

    @Hixie Thanks for the MediaQuery.of(context) suggestion (Ironically, I have used this in an earlier experiment but thought the ui.window.physicalSize is simpler and I can use it without context. Bad idea apparently).

    Appreciate the super quick responses on the weekend, feel free to close this (or let me know if I should).

    Thanks to both, (also for an amazing framework)

  8. Hixie commented on Aug 20, 2017

    @Hixie
    Contributor

    @mzimmerm Did you look at any of the documentation when switching from MediaQuery.of to ui.window? I'm curious if there's anywhere in the docs we could describe the trade-offs such that you would have seen it.

  9. added this to the milestone on Aug 20, 2017
  10. changed the title [-] ui.window.physicalSize inside build() reported incorrectly as (0,0) on first run[/-] [+]Discuss MediaQuery.of in ui.window documentation[/+] on Aug 20, 2017
  11. mzimmerm commented on Aug 20, 2017

    @mzimmerm
    Author

    @Hixie I did look at the docs, although I cannot claim the docs are misleading in any way. I pretty much live and try to find my info in

    https://docs.flutter.io/index.html

    Well, to give details: I am converting a simple charting library from Android to Flutter, and started looking at what in Flutter replaces

    Android scale : context.getResources().getDisplayMetrics().density;
    one way or another, I found this (still in my code)

    final widgets.MediaQueryData mediaQueryData = widgets.MediaQuery.of(context);
    double scale = mediaQueryData.devicePixelRatio;

    Then at some point I was looking at the docs of Window, and found:

    https://docs.flutter.io/flutter/dart-ui/Window/physicalSize.html

    and thought "ok I can use this instead", this is simple - the text about WidgetsBindingObserver I probably ignored as I did not 'get' it.

    If anything, I'd probably add to

    https://docs.flutter.io/flutter/dart-ui/Window/physicalSize.html

    something about using widgets.MediaQuery.of(context); instead with a bit of explanation. Perhaps there are other Window properties that have a similar problem.

    Sorry for the long comment, wanted to give context.

  12. Hixie commented on Aug 20, 2017

    @Hixie
    Contributor

    Fantastic, thanks. That's exactly what we needed to know! We'll add some docs there.

  13. mzimmerm commented on Aug 20, 2017

    @mzimmerm
    Author

    Happy to help in a small way. The Flutter team is doing amazing work, imho.

  14. added
    frameworkflutter/packages/flutter repository. See also f: labels.
    on Dec 3, 2018
  15. 32 remaining items

  16. martin-braun commented on Jul 20, 2023

    @martin-braun

    @Hixie Thanks for making this more clear to others. 👍

  17. github-actions commented on Aug 3, 2023

    @github-actions

    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 -v and a minimal reproduction of the issue.

  18. locked as resolved and limited conversation to collaborators on Aug 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

P2Important issues not at the top of the work listd: api docsIssues with https://api.flutter.dev/found in release: 3.3Found to occur in 3.3found in release: 3.7Found to occur in 3.7frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer versionteam-frameworkOwned by Framework teamtriaged-frameworkTriaged by Framework team

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions