Skip to content

context.mounted gives Don't use 'BuildContext's across async gaps message. #116779

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
RoarGronmo opened this issue Dec 9, 2022 · 15 comments
Closed
Labels
dependency: dart Dart team may need to help us framework flutter/packages/flutter repository. See also f: labels. P2 Important issues not at the top of the work list r: invalid Issue is closed as not valid

Comments

@RoarGronmo
Copy link

After upgrading to Flutter 3.7.0-1.1.pre on channel beta the context.mounted is flagged in use after async gap

I thought in my simple mind that context.mounted was "allowed" to be in use after async gap to detect valid context. If this should be so, what should we use instead to detect context validity ?

image

@darshankawar darshankawar added the in triage Presently being triaged by the triage team label Dec 12, 2022
@darshankawar
Copy link
Member

Thanks for the report @RoarGronmo
Can you check this comment and see if it helps in your case ?

@darshankawar darshankawar added the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Dec 12, 2022
@RoarGronmo
Copy link
Author

I think it hasn't any practical issue, other that Lint is flagging it as "suspicius", when it wasn't "suspicius" in versions prior to 3.7.x.

But if it is "suspicius" after 3.7, how can we test the availability of context, when we cannot use context.mounted ?

@github-actions github-actions bot removed the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Dec 12, 2022
@RoarGronmo
Copy link
Author

BTW: As you see from the code suggestion which Flutter gives above, method is to use context.mounted as described.

@darshankawar
Copy link
Member

Thanks for the update. Keeping this issue open and labeling for team's attention and insights.

@darshankawar darshankawar added framework flutter/packages/flutter repository. See also f: labels. documentation and removed in triage Presently being triaged by the triage team labels Dec 13, 2022
@darshankawar
Copy link
Member

/cc @goderbauer

@goderbauer
Copy link
Member

@RoarGronmo Could you please post some real example code that reproduces this warning? I tried to reproduce it with the following code, but it was behaving as expected:

import 'package:flutter/material.dart';

Future<void> foo(BuildContext context) async {
  await Future.delayed(const Duration(seconds: 1));
  Material.of(context); // produces warning, as expected.
  if (context.mounted) { // no warning, as expected.
    Material.of(context); // no warning, as expected.
  }
}

@goderbauer goderbauer added the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Dec 13, 2022
@RoarGronmo
Copy link
Author

Well, posting 550 lines not so suitable but I will give some more basic info first, that might give you some clues:

PS C:\FlutterProjects\mwork> flutter upgrade
Flutter is already up to date on channel beta
Flutter 3.7.0-1.1.pre • channel beta • https://github.com/flutter/flutter.git
Framework • revision e599f02c7a (8 days ago) • 2022-12-08 01:07:24 +0530
Engine • revision 4971c5b2e7
Tools • Dart 2.19.0 (build 2.19.0-444.1.beta) • DevTools 2.20.0
Android Studio Dolphin | 2021.3.1 Patch 1
Build #AI-213.7172.25.2113.9123335, built on September 30, 2022
Runtime version: 11.0.13+0-b1751.21-8125866 amd64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
Windows 11 10.0
GC: G1 Young Generation, G1 Old Generation
Memory: 4096M
Cores: 8
Registry:
    external.system.auto.import.disabled=true
    ide.text.editor.with.preview.show.floating.toolbar=false

Non-Bundled Plugins:
    org.jetbrains.kotlin (213-1.8.0-RC-release-311-AS6777.52)
    Dart (213.7433)
    io.flutter (71.1.3)
PS C:\FlutterProjects\mwork> flutter doctor -v
[√] Flutter (Channel beta, 3.7.0-1.1.pre, on Microsoft Windows [Version 10.0.22621.900], locale nb-NO)
    • Flutter version 3.7.0-1.1.pre on channel beta at c:\Flutter\flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision e599f02c7a (8 days ago), 2022-12-08 01:07:24 +0530
    • Engine revision 4971c5b2e7
    • Dart version 2.19.0 (build 2.19.0-444.1.beta)
    • DevTools version 2.20.0

[√] Windows Version (Installed version of Windows is version 10 or higher)

[√] Android toolchain - develop for Android devices (Android SDK version 33.0.1)
    • Android SDK at C:\Users\roarg\AppData\Local\Android\Sdk
    • Platform android-TiramisuPrivacySandbox, build-tools 33.0.1
    • ANDROID_HOME = C:\Users\roarg\AppData\Local\Android\Sdk
    • Java binary at: C:\Program Files\Android Studio\Android Studio 2021.3.1.17\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)
    • All Android licenses accepted.

[√] Chrome - develop for the web
    • Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe

[√] Visual Studio - develop for Windows (Visual Studio Community 2019 16.11.3)
    • Visual Studio at C:\Program Files (x86)\Microsoft Visual Studio\2019\Community
    • Visual Studio Community 2019 version 16.11.31702.278
    • Windows 10 SDK version 10.0.19041.0

[√] Android Studio (version 2021.1)
    • Android Studio at C:\Program Files\Android Studio\Android Studio 2021.1.1.23
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.11+9-b60-7590822)

[√] Android Studio (version 2021.2)
    • Android Studio at C:\Program Files\Android Studio\Android Studio 2021.2.1.16
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.12+7-b1504.28-7817840)

[√] Android Studio (version 2021.3)
    • Android Studio at C:\Program Files\Android Studio\Android Studio 2021.3.1.17
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)

[!] Android Studio (version 2022.1)
    • Android Studio at C:\Program Files\Android Studio\Android Studio 2022.1.1.16
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    X Unable to find bundled Java version.
    • Try updating or re-installing Android Studio.

[√] Android Studio (version 2021.3)
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    X Unable to find bundled Java version.
    • Try updating or re-installing Android Studio.

[√] Connected device (4 available)
    • sdk gphone64 x86 64 (mobile) • emulator-5554 • android-x64    • Android 13 (API 33) (emulator)
    • Windows (desktop)            • windows       • windows-x64    • Microsoft Windows [Version 10.0.22621.900]
    • Chrome (web)                 • chrome        • web-javascript • Google Chrome 108.0.5359.100
    • Edge (web)                   • edge          • web-javascript • Microsoft Edge 106.0.1370.52

[√] HTTP Host Availability
    • All required HTTP hosts are available

! Doctor found issues in 3 categories.

pubspec.yaml

name: mwork
description: A tool for handling orders in Norva24.

# The following line prevents the package from being accidentally published to
# pub.dev using `flutter pub publish`. This is preferred for private packages.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev

# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43
# followed by an optional build number separated by a +.
# Both the version and the builder number may be overridden in flutter
# build by specifying --build-name and --build-number, respectively.
# In Android, build-name is used as versionName while build-number used as versionCode.
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 0.1.1+18

environment:
  sdk: ">=2.16.0-80.1.beta <4.0.0"

# Dependencies specify other packages that your package needs in order to work.
# To automatically upgrade your package dependencies to the latest versions
# consider running `flutter pub upgrade --major-versions`. Alternatively,
# dependencies can be manually updated by changing the version numbers below to
# the latest version available on pub.dev. To see which dependencies have newer
# versions available, run `flutter pub outdated`.
dependencies:

  #_fe_analyzer_shared: ^40.0.0
  #analyzer: ^4.1.0
  #camera_web: ^0.3.0
  #characters: ^1.2.1
  #material_color_utilities: ^0.1.5


  #flutter_webview_plugin:
  #  git: https://github.com/nuc134r/flutter_webview_plugin.git

  msal_js: ^2.14.0
  aad_oauth: ^0.4.1
  provider: ^6.0.3
  path_to_regexp: ^0.4.0
  quiver: ^3.1.0
  #introduction_screen: ^3.0.2
  intl: ^0.18.0
  #socket_io_client: ^2.0.0-beta.4-nullsafety.0
  flutter:
    sdk: flutter

  #--jwt--- makes it possible to analyze jwt

  jwt_decode: ^0.3.1

  #---Swagger changes---
  chopper: 5.1.0
  json_annotation: ^4.5.0

  #---Google Maps---
  google_maps_flutter: ^2.1.7
  google_maps_flutter_web: ^0.4.0

  #---Location data (GPS)---
  #location: ^4.4.0
  location: ^5.0.0-dev.8

  #---Get---
  get: ^4.6.5

  #---Flutter Bloc---
  flutter_bloc: ^8.0.1

  #---Settings / preferences ---
  #flutter_settings_screens: ^0.3.2-null-safety
  pref: ^2.6.0

  #---Camera function---
  camera: ^0.10.0+1
  path_provider: ^2.0.11
  path: ^1.8.1

  #---Floor functionality---
  #floor: ^1.2.0

  #---Drift functionality---
  drift: ^2.1.0
  #drift:
  #  git:
  #    url: https://github.com/simolus3/drift.git
  #    ref: develop
  #    path: drift
  #drift: 1.7.1
  sqlite3_flutter_libs: ^0.5.7


  #---Url launcher
  url_launcher: ^6.1.3

  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.5

  #---badges for icons
  badges: ^2.0.3

  #---flutter webview plugin displace
  #flutter_webview_plugin:
  #    git: https://github.com/nuc134r/flutter_webview_plugin.git

  #---logging:
  logging: ^1.0.2
  firebase_core: ^2.0.0
  firebase_crashlytics: ^3.0.1
  package_info_plus: ^3.0.0
  firebase_performance: ^0.9.0+1

  #---db_inspector
  drift_db_viewer: ^2.0.0

  #---validators
  email_validator: ^2.1.17

  #---list extensions
  collection: ^1.16.0

  #---flag
  flag: ^6.0.0

#---Icons---



flutter_icons:
  android: "launcher_icon"
  ios: true
  image_path: "assets/icons/logo_round.png"
  adaptive_icon_background: "#666666"

dev_dependencies:
  flutter_test:
    sdk: flutter

  #---swagger changes---
  build_runner: ^2.1.11
  chopper_generator: 5.1.0
  json_serializable: ^6.2.0
  swagger_dart_code_generator: ^2.8.7

  #---Launcher icons---
  flutter_launcher_icons: ^0.11.0

  #---floor generators---
  #floor_generator: ^1.2.0

  #---drift generators---
  drift_dev: ^2.1.0
  #drift_dev: 1.7.1

  #--- analyzer
  #analyzer: ^4.1.0

  # The "flutter_lints" package below contains a set of recommended lints to
  # encourage good coding practices. The lint set provided by the package is
  # activated in the `analysis_options.yaml` file located at the root of your
  # package. See that file for information about deactivating specific lint
  # rules and activating additional ones.
  flutter_lints: ^2.0.1

# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec

# The following section is specific to Flutter.
flutter:

  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true

  # To add assets to your application, add an assets section, like this:
  assets:
    - assets/icons/


  # An image asset can refer to one or more resolution-specific "variants", see
  # https://flutter.dev/assets-and-images/#resolution-aware.

  # For details regarding adding assets from package dependencies, see
  # https://flutter.dev/assets-and-images/#from-packages

  # To add custom fonts to your application, add a fonts section here,
  # in this "flutter" section. Each entry in this list should have a
  # "family" key with the font family name, and a "fonts" key with a
  # list giving the asset and other descriptors for the font. For
  # example:
  # fonts:
  #   - family: Schyler
  #     fonts:
  #       - asset: fonts/Schyler-Regular.ttf
  #       - asset: fonts/Schyler-Italic.ttf
  #         style: italic
  #   - family: Trajan Pro
  #     fonts:
  #       - asset: fonts/TrajanPro.ttf
  #       - asset: fonts/TrajanPro_Bold.ttf
  #         weight: 700
  #
  # For details regarding fonts from package dependencies,
  # see https://flutter.dev/custom-fonts/#from-packages

A simple timeline scheme (extraction):

import 'dart:ui';

import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:mwork/common/extensions.dart';
import 'package:mwork/common/globals.dart' as globals;
import 'package:drift/drift.dart' as drift;
import 'package:mwork/functions/loaders.dart';
import 'package:mwork/functions/processors.dart';
import 'package:mwork/utils/widgets/icon_field.dart';

import '../../../../functions/selectors.dart';
import '../../../../services/drift/database/m_work_database.dart';
import '../../../../utils/widgets/flex_icon_field.dart';
import '../../../message/message.dart';
import '../../settings/setting_keys.dart';

class TimelineTabCurrentDay extends StatefulWidget{
  final int date;
  final ScrollController scrollController;
  const TimelineTabCurrentDay({
    Key? key,
    required this.date,
    required this.scrollController
  }) : super(key: key);

  @override
  State<TimelineTabCurrentDay> createState() => _TimelineTabCurrentDayState();
}

class _TimelineTabCurrentDayState extends State<TimelineTabCurrentDay> {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build

    print("date = ${widget.date}");

    return Scrollbar(
      controller: widget.scrollController,
      thumbVisibility: true,
      child: ScrollConfiguration(
          behavior: ScrollConfiguration.of(context).copyWith(
              dragDevices: {
                PointerDeviceKind.touch,
                PointerDeviceKind.mouse
              }
          ),
        child: RefreshIndicator(
          onRefresh: () async {
            var selectedFirm = await globals.mWorkDatabase.getSelectedFirm(
                SettingKey.userSelectionSelectedFirm,
                SettingKey.userSelectionSelectedCountry).getSingleOrNull();
            if(selectedFirm==null){
              Message.error(context.mounted?context:null,"Firm not selected! Could not refresh data from server!");
            } else {
              await getUserActivities(
                  frmNo: selectedFirm.frmNo,
                  frmHash: selectedFirm.hash,
                  frDt: widget.date);
            }
          },
          child: StreamBuilder(
            stream: globals.mWorkDatabase.getMyDayActivityAppointments(widget.date, widget.date).watch(),
            builder: (context, snapshot){
              if(snapshot.hasError){
                return Card(
                  color: Colors.red,
                  child: Text(snapshot.error.toString(), style: TextStyle(color: Colors.yellow)),
                );
              }

              List<ActivityAppointment> activities = [];

              if(snapshot.hasData){
                activities = snapshot.data as List<ActivityAppointment>;
              }

              print("scrollbar activities = $activities");

              return ListView.builder(
                controller: widget.scrollController,
                itemCount: activities.length,
                  itemBuilder: (context, index){
                      var activity = activities[index];

                      print("activity = $activity");

                      switch(activity.rspTp){
                        case null:
                          return const SizedBox.shrink(); //No data for null
                        case 1:
                          return InkWell(
                            onTap: (){
                              selectTime(context: context, dateTime: DateTime(0,1,1,((activity.frTm??0)~/100),((activity.frTm??0).remainder(100)))).then((value){

                              });
                            },
                            child: Card(
                              shape:RoundedRectangleBorder(
                                  side: const BorderSide(width: 1),
                                  borderRadius: BorderRadius.circular(4)
                              ),
                              color: Colors.orange[300],
                              child: Column(
                                children: [
                                  Row(
                                    children: [
                                      FlexIconField(
                                        iconData: Icons.punch_clock,
                                        text: activity.frTm.to24HoursMinuteString(),
                                        fillColor: Colors.orange,
                                        flex: 25,
                                      ),
                                      FlexIconField(
                                        iconData: Icons.today,
                                        text: activity.frDt.toDateMonthYearString(),
                                        fillColor: Colors.orange,
                                        flex: 33,
                                      ),
                                      FlexIconField(
                                        iconData: Icons.category,
                                        text: "Punched in !",
                                        flex: 62,
                                        fillColor: Colors.orange,
                                      )
                                    ],
                                  ),

                                  activity.newNo!=0?Row(
                                    children: [
                                      FlexIconField(
                                          iconData: Icons.warning_amber,
                                          text: "Not server registered",
                                          fillColor: Colors.red[400]
                                      ),
                                      Padding(
                                        padding: const EdgeInsets.only(right: 4.0),
                                        child: ElevatedButton(
                                          onPressed: () {


                                          },
                                          child: Row(
                                            children: const [
                                              Icon(Icons.send),
                                              SizedBox(width: 4,),
                                              Text("Register"),
                                            ],
                                          ),
                                        ),
                                      ),
                                    ],
                                  ):const SizedBox.shrink()

                                ],
                              ),
                            ),
                          );


                          break;
                        case 2:
                          return Card(
                            shape: RoundedRectangleBorder(
                                side: const BorderSide(width: 1),
                                borderRadius: BorderRadius.circular(4)
                            ),
                            color: Colors.green[200],
                            child: Column(
                              children: [
                                Row(
                                  children: [
                                    FlexIconField(
                                      iconData: Icons.start,
                                      text:activity.frTm.to24HoursMinuteString(),
                                      //text:"23:45",
                                      flex: 28
                                    ),
                                    FlexIconField(
                                        iconData: Icons.timer_outlined,
                                        text:activity.noReg.fromMinutesTo24HourMinuteString(),
                                        flex: 28
                                    ),
                                    FlexIconField(
                                      iconData: Icons.keyboard_tab,
                                      text:activity.toTm.to24HoursMinuteString(),
                                      flex: 28
                                    ),

                                    const FlexIconField(
                                        iconData: Icons.category,
                                      text: "Assignment",
                                      flex: 50
                                    ),
                                  ],
                                ),
                                Row(
                                  children: [
                                    FlexIconField(
                                      iconData: Icons.assignment_turned_in,
                                      text: "${activity.ordNo}",
                                      flex: 26,
                                    ),
                                    FlexIconField(
                                      iconData: Icons.format_list_numbered,
                                      text: "${activity.ordLnNo}",
                                      flex: 18
                                    ),
                                    FlexIconField(
                                      iconData: Icons.engineering,
                                      text: "${activity.descr}",
                                      flex: 56
                                    )
                                  ],
                                )

                              ],
                            ),
                          );


                          //TODO Production
                        break;

                        case 12:

                          return InkWell(
                            onTap: (){
                              selectTime(context: context, dateTime: DateTime(0,1,1,((activity.frTm??0)~/100),((activity.frTm??0).remainder(100)))).then((value) async {

                                var selectedFirm = await globals.mWorkDatabase.getSelectedFirm(SettingKey.userSelectionSelectedFirm, SettingKey.userSelectionSelectedCountry).getSingleOrNull();

                                var me = await globals.mWorkDatabase.getMe().getSingleOrNull();

                                if(value==null){
                                  Message.info(context.mounted?context:null, "Nothing changed !" );
                                } else if((me==null)||(selectedFirm==null)){

                                } else {
                                  await activityAppointmentCreateSendProcessor(
                                      context: context.mounted ? context : null,
                                      empNo: me.empNo,
                                      frmNo: selectedFirm.frmNo,
                                      frmHash: selectedFirm.hash,
                                      frDt: activity.frDt??0,
                                      frTm: value.hour*100+value.minute,
                                      toDt: activity.toDt??0,
                                      toTm: value.hour*100+value.minute,
                                      rspTp: 12);
                                }
                                /*
                                await createMeActivityAppointment(
                                    frmNo: activity.frmNo??0,
                                    frDt: activity.frDt,
                                    frTm: (value?.hour??0)*100+(value?.minute??0),
                                    toDt: activity.toDt,
                                    toTm: (value?.hour??0)*100+(value?.minute??0),
                                    rspTp: 12
                                );*/
                              });
                            },
                            child: Card(
                              shape:RoundedRectangleBorder(
                                  side: const BorderSide(width: 1),
                                  borderRadius: BorderRadius.circular(4)
                              ),
                              color: Colors.orange[300],
                              child: Column(
                                children: [
                                  Row(
                                    children: [
                                      FlexIconField(
                                        iconData: Icons.punch_clock_outlined,
                                        text: activity.frTm.to24HoursMinuteString(),
                                        fillColor: Colors.orange,
                                        flex: 25,
                                      ),
                                      FlexIconField(
                                        iconData: Icons.today,
                                        text: activity.frDt.toDateMonthYearString(),
                                        fillColor: Colors.orange,
                                        flex: 33,
                                      ),
                                      const FlexIconField(
                                        iconData: Icons.category,
                                        text: "Punched out !",
                                        flex: 62,
                                        fillColor: Colors.orange,
                                      )
                                    ],
                                  ),

                                  activity.newNo!=0?Row(
                                    children: [
                                      FlexIconField(
                                          iconData: Icons.warning_amber,
                                          text: "Not server registered",
                                          fillColor: Colors.red[400]
                                      ),
                                      Padding(
                                        padding: const EdgeInsets.only(right: 4.0),
                                        child: ElevatedButton(
                                          onPressed: () {


                                          },
                                          child: Row(
                                            children: const [
                                              Icon(Icons.send),
                                              SizedBox(width: 4,),
                                              Text("Register"),
                                            ],
                                          ),
                                        ),
                                      ),
                                    ],
                                  ):const SizedBox.shrink()

                                ],
                              ),
                            ),
                          );

                          break;

                        default :

                          return Card(
                            shape:RoundedRectangleBorder(
                                side: const BorderSide(width: 1),
                                borderRadius: BorderRadius.circular(4)
                            ),
                            color: Colors.blueGrey[300],
                            child: Column(
                              children: [
                                Row(
                                  children: [
                                    FlexIconField(
                                        iconData: Icons.start,
                                        text:activity.frTm.to24HoursMinuteString(),
                                        //text:"23:45",
                                        flex: 28
                                    ),
                                    FlexIconField(
                                        iconData: Icons.timer_outlined,
                                        text:activity.noReg.fromMinutesTo24HourMinuteString(),
                                        flex: 28
                                    ),
                                    FlexIconField(
                                        iconData: Icons.keyboard_tab,
                                        text:activity.toTm.to24HoursMinuteString(),
                                        flex: 28
                                    ),

                                    Flexible(
                                      flex: 50,
                                      child: StreamBuilder(
                                        stream: globals.mWorkDatabase.getActivityResponseTypes().watch(),
                                        builder: (context, snapshot) {

                                          var responseTypes = snapshot.data as List<ActivityResponseType?>?;

                                          if(responseTypes == null || responseTypes.isEmpty){
                                            return PopupMenuButton(
                                              itemBuilder: (context){
                                                return[
                                                  const PopupMenuItem(
                                                      child: Text("<No entries>", style:TextStyle(color: Colors.red))
                                                  )
                                                ];
                                              },
                                              child: IconField(
                                                iconData: Icons.category,
                                                text: "${activity.rspTp??""}",
                                              ),
                                            );
                                          } else
                                          {
                                            return PopupMenuButton<int>(
                                              child: IconField(
                                                iconData: Icons.category,
                                                text: "${responseTypes[activity.rspTp??0]?.descr??"--"}",
                                              ),
                                              onSelected: (index) async {
                                                await globals.mWorkDatabase.updateActivityAppointmentCategory(
                                                  responseTypes[index]?.rspTpNo,
                                                  activity.newNo,
                                                  activity.agrNo
                                                );
                                              },
                                              itemBuilder: (context){
                                                return responseTypes.mapIndexed((index, responseType){
                                                  return PopupMenuItem(
                                                    value: index,
                                                    child: Row(
                                                      children: [
                                                        FlexIconField(
                                                          iconData: Icons.category_outlined,
                                                          text: "${responseType?.rspTpNo??"--"}",
                                                          flex: 4,
                                                        ),
                                                        FlexIconField(
                                                            iconData: Icons.category,
                                                            text: "${responseType?.descr??"--"}",
                                                          flex: 6,
                                                        )
                                                      ]
                                                    )
                                                  );
                                                }).toList();
                                              },
                                            );
                                          }

                                        }
                                      ),
                                    ),
/*
                                    FlexIconField(
                                        iconData: Icons.category,
                                        text: "${activity.rspTp??""}",
                                        flex: 50,
                                        onTap: (){

                                        },


                                    ),*/
                                  ],
                                ),
                                ((activity.newNo!=0)||(activity.isChanged==true))?Row(
                                  children: [
                                    FlexIconField(
                                      iconData: Icons.warning_amber,
                                      text: "Not server registered",
                                      fillColor: Colors.red[400],
                                    ),
                                    Padding(
                                      padding: const EdgeInsets.only(right: 4.0),
                                      child: ElevatedButton(
                                        onPressed: () async {

                                          var selectedFirm = await globals.mWorkDatabase.getSelectedFirm(SettingKey.userSelectionSelectedFirm, SettingKey.userSelectionSelectedCountry).getSingleOrNull();

                                          await activityAppointmentCreateSendProcessor(
                                              context: context.mounted?context:null,
                                              empNo: activity.empNo,
                                              frmNo: activity.frmNo??0,
                                              frmHash: selectedFirm?.hash??"",
                                              frDt: activity.frDt??0,
                                              frTm: activity.frTm??0,
                                              toDt: activity.toDt??0,
                                              toTm: activity.toTm??0,
                                              rspTp: activity.rspTp??0);

                                        },
                                        child: Row(
                                          children: const [
                                            Icon(Icons.send),
                                            SizedBox(width: 4,),
                                            Text("Register"),
                                          ],
                                        ),
                                      ),
                                    ),
                                  ],
                                ):const SizedBox.shrink()
                              ],
                            ),
                          );

                          break;



                      }



                      return Text("${activities[index].agrNo}: ${activities[index].frDt}"); //Fail-over returns
                  });


              return Text("Text");  //Fail-over returns
            }
          ),
        ),
      ),
    );
  }
}

You will certainly not let it work since you miss some internal libraries, but the clue is: context.mounted is "linting".

Note: the context.mounted references appears in lines: 54, 236, 241, 447

@github-actions github-actions bot removed the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Dec 15, 2022
@RoarGronmo
Copy link
Author

Addendum:

Below, I tried to add your code into the class where this problem appears, and sees that your example appears correctly, and it simultaniously "lints" the usage of context.mounted in my existing code further down. BTW: This worked perfectly in beta 3.6, the bug seems to have been introduced in beta 3.7.

I think you need to get som oxygen and dive deeper into this behavior ;)

See picture:
image

@goderbauer
Copy link
Member

@RoarGronmo Can you reduce the code sample that shows the erroneous behavior by removing subsequently removing all the stuff that isn't relevant? That will make it easier to debug this.

@goderbauer goderbauer added waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds dependency: dart Dart team may need to help us P2 Important issues not at the top of the work list labels Dec 20, 2022
@RoarGronmo
Copy link
Author

I have reworked the standard example to launch an AlertDialog with two buttons to mimick a delay.

As far as I see, the clue is that if(context.mounted) does not trigger message, but context.mounted?true:false trigger the message. You should make it possible to use context.mounted as a single legitim test, to avoid using if overall.

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() async {



    setState(() {
      // This call to setState tells the Flutter framework that something has
      // changed in this State, which causes it to rerun the build method below
      // so that the display can reflect the updated values. If we changed
      // _counter without calling setState(), then the build method would not be
      // called again, and so nothing would appear to happen.
      _counter++;
    });
  }

  Future<int> longTime(int time) async {

    await Future.delayed(Duration(seconds: time),(){});

    return time;
  }

  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
      ),
      body: Center(
        // Center is a layout widget. It takes a single child and positions it
        // in the middle of the parent.
        child: Column(
          // Column is also a layout widget. It takes a list of children and
          // arranges them vertically. By default, it sizes itself to fit its
          // children horizontally, and tries to be as tall as its parent.
          //
          // Invoke "debug painting" (press "p" in the console, choose the
          // "Toggle Debug Paint" action from the Flutter Inspector in Android
          // Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
          // to see the wireframe for each widget.
          //
          // Column has various properties to control how it sizes itself and
          // how it positions its children. Here we use mainAxisAlignment to
          // center the children vertically; the main axis here is the vertical
          // axis because Columns are vertical (the cross axis would be
          // horizontal).
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        //onPressed: _incrementCounter,
        onPressed: () {
          showDialog(
            context: context,
            builder: (builderContext){
              return AlertDialog(
                title: Text("Test"),
                actions: [
                  ElevatedButton(onPressed: () async {
                    var value = await longTime(10);

                    if(context.mounted) print("context is mounted: var = $value");

                    print("context mounted = ${context.mounted}: var = $value");
                    print("builderContext mounted = ${builderContext.mounted}: var = $value");

                    if(builderContext.mounted) Navigator.pop(builderContext);

                  }, child: Text("10 secs")),
                  ElevatedButton(onPressed: () async {
                    var value = await longTime(1);

                    print("context mounted = ${context.mounted}: var = $value");
                    print("builderContext mounted = ${builderContext.mounted}: var = $value");

                    if(context.mounted) print("context is mounted: var = $value");

                    if(builderContext.mounted) Navigator.pop(builderContext);

                  }, child: Text("1 secs"))
                ],

              );
            }
          );
        },
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

image

I hope this give you a clue !

-- Merry X-mas --

@github-actions github-actions bot removed the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Dec 21, 2022
@luccasclezar
Copy link
Contributor

luccasclezar commented Jan 25, 2023

After upgrading to Flutter 3.7, I'm experiencing the same issue in VS Code.

Besides the ternary operator, using !context.mounted results in the same warning.

It's pretty simple to reproduce:

  1. Create a new project with flutter create
  2. Then add this code to main.dart
class AsyncContextTestWidget extends StatelessWidget {
  const AsyncContextTestWidget({super.key});

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () async {
        await Future<void>.delayed(Duration.zero);

        if (!context.mounted) {
          return;
        }
      },
      child: const Text('Test'),
    );
  }
}

@goderbauer
Copy link
Member

@luccasclezar Could you file an issue with that repo case at https://github.com/dart-lang/linter/ and cc me please? It looks like the lint has a bug.

@luccasclezar
Copy link
Contributor

@goderbauer Done! 🙂

dart-lang/sdk#59009

@goderbauer
Copy link
Member

Closing this here since we are tracking the problem now at dart-lang/sdk#59009.

@github-actions
Copy link

github-actions bot commented Mar 4, 2023

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.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 4, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
dependency: dart Dart team may need to help us framework flutter/packages/flutter repository. See also f: labels. P2 Important issues not at the top of the work list r: invalid Issue is closed as not valid
Projects
None yet
Development

No branches or pull requests

4 participants