Search code examples
flutterflutter-futurebuilderflutter-alertdialog

Flutter - Multiple Future with error "type 'Null' is not a subtype of type 'Widget'"


I've build a simple Splash screen. I'm using this package. Now, I'm trying to add version checker via Firebase Remote Config to my Splash Screen. I've written simple version checker code:

Future<bool> versionCheck(context) async {
  //Get Current installed version of app
  final PackageInfo info = await PackageInfo.fromPlatform();
  double currentVersion = double.parse(info.version.trim().replaceAll(".", ""));

  //Get Latest version info from firebase config
  final FirebaseRemoteConfig _remoteConfig = FirebaseRemoteConfig.instance;

  // Using default duration to force fetching from remote server.
  try {
    await _remoteConfig.setConfigSettings(RemoteConfigSettings(
      // cache refresh time
      fetchTimeout: const Duration(seconds: 1),
      // a fetch will wait up to 3 seconds before timing out
      minimumFetchInterval: const Duration(seconds: 3),
    ));
    await _remoteConfig.fetchAndActivate();
    _remoteConfig.getString('force_update_current_version');
    double newVersion = double.parse(_remoteConfig
        .getString('force_update_current_version')
        .trim()
        .replaceAll(".", ""));
    if (newVersion > currentVersion) {
      return false;
    } else {
      return true;
    }
  } catch (exception) {
    return false;
  }
}

I've tested it on my another screen. It works fine.

When I try to add this control to my Splash screen, it says type 'Null' is not a subtype of type 'Widget'

I'm getting my show boolean from SharedPreferences via my checkOnBoarding() method and works well, but when I try to add version control, I fail.

Here it is my Splash Screen code:

class SplashScreen extends StatefulWidget
{
  @override
  _SplashScreenState createState() => _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen> {
  bool show = true;
  bool versionOK = false;

  @override
  void initState() {
    checkVersion();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () {
        return Future.value(false);
      },
      child: AnimatedSplashScreen(
        backgroundColor: Colors.white,
        splash: "images/my-logo.png",
        nextScreen: FutureBuilder(
          future: checkOnBoarding(),
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              if(snapshot.data == true){
                if(versionOK){
                  return MainScreen();
                } else {
                  return showVersionDialog(context);
                }
              }
              else{
                return IntroScreen();
              }
            } else {
              return CircularProgressIndicator();
            }
          },
        ),
        splashTransition: SplashTransition.sizeTransition,
        duration: 3000,
      ),
    );
  }

  Future<bool> checkVersion() async{
    versionOK = await versionCheck(context);
    return versionOK;
  }

  Future<bool> checkOnBoarding() async{
    final prefs = await SharedPreferences.getInstance();
    show = prefs.getBool('ON_BOARDING') ?? false;
    return show;
  }

  showVersionDialog(context) {
    Future.delayed(Duration.zero,(){
      showDialog<String>(
        context: context,
        barrierDismissible: false,
        builder: (BuildContext context) {
          String title = "New Update Available";
          String message =
              "There is a newer version of app available please update it now.";
          String btnLabel = "OK";
          return Platform.isIOS
              ? new CupertinoAlertDialog(
            title: Text(title),
            content: Text(message),
            actions: <Widget>[
              ElevatedButton(
                child: Text(btnLabel),
                onPressed: () {
                  exit(0);
                },
              ),
            ],
          )
              : new AlertDialog(
            title: Text(title),
            content: Text(message),
            actions: <Widget>[
              ElevatedButton(
                child: Text(btnLabel),
                onPressed: () {
                  SystemNavigator.pop();
                },
              ),
            ],
          );
        },
      );
    });

  }
}

So as you see, after I get my show boolean from SharedPreference, I want to check versionOK and if it false, I want to show a non-dissmisable dialog with one button (via my showVersionDialog method). If it comes true, I want to navigate my Main Screen.

What am I missing?


Solution

  • The issue is showVersionDialog doesn't return a widget.

      showVersionDialog(context) {
        _dialog(context);
        return Scaffold();
      }
    
      _dialog(context) {
        Future.delayed(Duration.zero, () {
          showDialog<String>(
            context: context,
            barrierDismissible: false,
            builder: (BuildContext context) {
              String title = "New Update Available";
              String message =
                  "There is a newer version of app available please update it now.";
              String btnLabel = "OK";
              return AlertDialog(
                title: Text(title),
                content: Text(message),
                actions: <Widget>[
                  ElevatedButton(
                    child: Text(btnLabel),
                    onPressed: () {},
                  ),
                ],
              );
            },
          );
        });
      }