OpenFlutter / flutter_screenutil

Flutter screen adaptation, font adaptation, get screen information
https://pub.dartlang.org/packages/flutter_screenutil
Apache License 2.0
3.88k stars 494 forks source link

[5.5.3+2] ScreenUtil.ensureScreenSize() randomly produces a Stack Overflow exception #402

Closed scottinet closed 2 years ago

scottinet commented 2 years ago

Report

ScreenUtil version: 5.5.3+2 OS: Android (did not test on iOS yet) Environment: reproduced in debug sessions, I cannot say for sure that this cannot happen in release builds Reproducable: yes, but it's random, and not very common

Context: I don't know if this is relevant (see below), but my app is an hybrid android/flutter app with a pre-warmed flutter engine. This error occurs when starting a flutter activity for the first time.

Minimum code to reproduce:

void main() async {
  await ScreenUtil.ensureScreenSize();
  runApp(FooApp());
}

Stacktrace:

[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: Stack Overflow
    #0      _completeOnAsyncError (dart:async-patch/async_patch.dart:266:1)
    #1      ScreenUtil.ensureScreenSize.<anonymous closure> (package:flutter_screenutil/src/screen_util.dart)
    #2      _rootRunUnary (dart:async/zone.dart:1434:47)
    #3      _CustomZone.runUnary (dart:async/zone.dart:1335:19)
    #4      _FutureListener.handleValue (dart:async/future_impl.dart:159:18)
    #5      Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:766:45)
    #6      Future._propagateToListeners (dart:async/future_impl.dart:795:13)
    #7      Future._completeWithValue (dart:async/future_impl.dart:601:5)
    #8      _completeOnAsyncReturn (dart:async-patch/async_patch.dart:262:13)
    #9      ScreenUtil.ensureScreenSize.<anonymous closure> (package:flutter_screenutil/src/screen_util.dart)
    #10     _rootRunUnary (dart:async/zone.dart:1434:47)
    #11     _CustomZone.runUnary (dart:async/zone.dart:1335:19)
    #12     _FutureListener.handleValue (dart:async/future_impl.dart:159:18)
    #13     Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:766:45)
    #14     Future._propagateToListeners (dart:async/future_impl.dart:795:13)
    #15     Future._completeWithValue (dart:async/future_impl.dart:601:5)
    #16     _completeOnAsyncReturn (dart:async-patch/async_patch.dart:262:13)
    #17     ScreenUtil.ensureScreenSize.<anonymous closure> (package:flutter_screenutil/src/screen_util.dart)
    #18     _rootRunUnary (dart:async/zone.dart:1434:47)
    #19     _CustomZone.runUnary (dart:async/zone.dart:1335:19)
    #20     _FutureListener.handleValue (dart:async/future_impl.dart:159:18)
    #21     Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:766:45)
    #22     Future._propagateToListeners (dart:async/future_impl.dart:795:13)
    #23     Future._completeWithValue (dart:async/future_impl.dart:601:5)
    #24     _completeOnAsyncReturn (dart:async-patch/async_patch.dart:262:13)
    #25     ScreenUtil.ensureScreenSize.<anonymous closure> (package:flutter_screenutil/src/screen_util.dart)
    #26     _rootRunUnary (dart:async/zone.dart:1434:47)
    #27     _CustomZone.runUnary (dart:async/zone.dart:1335:19)
    #28     _FutureListener.handleValue (dart:async/future_impl.dart:159:18)
    #29     Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:766:45)
    #30     Future._propagateToListeners (dart:async/future_impl.dart:795:13)
    #31     Future._completeWithValue (dart:async/future_impl.dart:601:5)
    #32     _completeOnAsyncReturn (dart:async-patch/async_patch.dart:262:13)
    #33     ScreenUtil.ensureScreenSize.<anonymous closure> (package:flutter_screenutil/src/screen_util.dart)
    #34     _rootRunUnary (dart:async/zone.dart:1434:47)
    #35     _CustomZone.runUnary (dart:async/zone.dart:1335:19)
    #36     _FutureListener.handleValue (dart:async/future_impl.dart:159:18)
    #37     Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:766:45)
    #38     Future._propagateToListeners (dart:async/future_impl.dart:795:13)
    ...
    ...
    #8230   _completeOnAsyncReturn (dart:async-patch/async_patch.dart:262:13)
    #8231   ScreenUtil.ensureScreenSize.<anonymous closure> (package:flutter_screenutil/src/screen_util.dart)
    #8232   _rootRunUnary (dart:async/zone.dart:1434:47)
    #8233   _CustomZone.runUnary (dart:async/zone.dart:1335:19)
    #8234   _FutureListener.handleValue (dart:async/future_impl.dart:159:18)
    #8235   Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:766:45)
    #8236   Future._propagateToListeners (dart:async/future_impl.dart:795:13)
    #8237   Future._completeWithValue (dart:async/future_impl.dart:601:5)
    #8238   _completeOnAsyncReturn (dart:async-patch/async_patch.dart:262:13)
    #8239   ScreenUtil.ensureScreenSize.<anonymous closure> (package:flutter_screenutil/src/screen_util.dart)
    #8240   _rootRunUnary (dart:async/zone.dart:1434:47)
    #8241   _CustomZone.runUnary (dart:async/zone.dart:1335:19)
    #8242   _FutureListener.handleValue (dart:async/future_impl.dart:159:18)

Analysis & workaround

It obviously comes from https://github.com/OpenFlutter/flutter_screenutil/blob/master/lib/src/screen_util.dart#L65 : if the app takes too much time to initialize its rendering environment, the ensureScreenSize performs too many iterations, or rather, too many recursive calls to itself.

In the meantime, I've added this in my code as a workaround:

  final binding = WidgetsFlutterBinding.ensureInitialized();
  final FlutterWindow window = binding.window;
  while (window.viewConfiguration.geometry.isEmpty) {
    await Future.delayed(const Duration(milliseconds: 10));
  }

  await ScreenUtil.ensureScreenSize();
github-actions[bot] commented 2 years ago

This issue is stale because it has been open for 30 days with no activity.

Mounir-Bouaiche commented 2 years ago

Thanks, we'll work on it.

github-actions[bot] commented 2 years ago

This issue is stale because it has been open for 30 days with no activity.

github-actions[bot] commented 2 years ago

This issue was closed because it has been inactive for 14 days since being marked as stale.