0

i have the code to check version of flutter app but it contains an asynchron code which i cannot insert inside buildcontext method, so i decided to put it into the main method and insert a popup to tell to the user he has to update the app but i received this reponse: failed assertion: Line 70 pos 15: context!=null:is not true because i set context to null in my alertDialog, so id don' tknow where to place it so that each time the user launches the app the version checking is running and shows the alertDialog if the version he has is less than the one in the store. here is my code to checked it and how i implemented it: i used the NewVersion package to chek and compare the local version and stored version in google play

  class PataStoreConnector extends StatefulWidget {
  final bool loggedin;
  PataStoreConnector({Key key, this.loggedin}) : super(key: key);

  @override
  _PataStoreConnectorState createState() => _PataStoreConnectorState();
}

class _PataStoreConnectorState extends State<PataStoreConnector> {
  bool sleeping = true;
  @override
  void initState() {
    WidgetsBinding.instance.addPostFrameCallback((_) {
      timer();
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    if (sleeping) {
      return PataSplashScreen();
    }
    return StoreConnector<PataState, PataViewModel>(
      converter: PataViewModel.convertStateToViewModel,
      builder: (BuildContext context, PataViewModel pataViewModel) {
        return getPage(pataViewModel);
      },
    );
  }

and the getPage method which contains the code for checking version:

   // ignore: missing_return
  Widget getPage(PataViewModel viewModel) {
    //Pt.instance.version;

final newVersion = NewVersion(
  androidId: 'com.snedac.empata',
  context: context,
);
// setState(() async {
//   VersionStatus vs = await newVersion.getVersionStatus();
// });
newVersion.getVersionStatus().then((result) {
  print("store version ${result.storeVersion}");
  print("local version ${result.localVersion}");
  if (result.storeVersion == result.localVersion) {
    if (viewModel.isLoggingIn()) {
      viewModel.refreshUserData();
      // vm.setIsHomeLoadedStateAction(true);
      return PataSplashScreen();
    }

    if (!viewModel.isLoggedIn()) {
      return LoginPage(
        viewModel: viewModel,
      );
    }
    print("homeloaded:${viewModel.state.isHomeloaded}");
    print("userIdLogin:${viewModel.state.user.userId}");
    if (viewModel.state.isHomeloaded == false) {
      if (viewModel.state.user.userId > 0) {
        viewModel.initHome();
      } else {
        return LoginPage(
          viewModel: viewModel,
        );
      }
    }
    return PataHome(title: "e-Mpata");
  } else {
    _ackAlert2("Mise a jour", 'Votre version est trop obsolète.');
  }
});

}

Ramses Kouam
  • 531
  • 5
  • 14
  • You should remove the line where you set buildcontext to null. ( I think thats bad practice) Maybe look here: https://stackoverflow.com/questions/53672171/how-to-get-build-and-version-number-of-flutter-app – SilkeNL May 31 '21 at 17:38

1 Answers1

0

You should never need to do async work in a build() method. If you want to display an error for an out of date version on startup, you could do some code like this:

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();  // make sure plugins are initialized properly
  final isOutOfDate = await checkAppOutOfDate();  // do the check
  runApp(MyApp(isOutOfDate: isOutOfDate));  // pass the boolean to your app as a parameter
}

Then, you can modify MyApp() (or whatever is at the root of your widget tree) to accept this parameter and handle it properly:

class MyApp extends StatefulWidget {
  final bool isOutOfDate;
  MyApp({required this.isOutOfDate});

  @override
  MyAppState createState() => MyAppState();

}

class MyAppState extends State<MyApp> {
  
  // a bit like initState(), but has access to a live BuildContext
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    
    if (widget.isOutOfDate) {
      showDialog(context, ...);  // show a dialog to the user with a proper BuildContext
    }
  }

  @override
  Widget build(BuildContext context) {
    ...
  }
}

If you would rather show the dialog in initState, you will have to delay showing it by some amount, e.g.:

@override
void initState() {
  super.initState();
  SchedulerBinding.instance!.addPostFrameCallback((_) => showDialog(context, ...));
}

But in this case, both will achieve similar results

cameron1024
  • 9,083
  • 2
  • 16
  • 36