Search code examples
flutterdartdart-async

How do I convert 'Future<String?>' to 'Future<String>?' in Flutter?


So basically Iam working with the network_info_plus package to read the current connected Wifiname of the device. I want to use a FutureBuilder to get the future from await info.getWifiName();. The problem is that the method returns a Future<String?>. What is the smartest way to convert this to Future<String>??

e.g.

    NetworkInfo info = NetworkInfo();
    ...
    FutureBuilder<String>(
    future: info.getWifiName(), // Error: The argument type 'Future<String?>' 
                                // can't be assigned to the parameter type 'Future<String>?'
    builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
        ...

Solution

  • If you look at the internal implementation of the getWifiName() function

      /// Obtains the wifi name (SSID) of the connected network
      ///
      /// Please note that it DOESN'T WORK on emulators (returns null).
      ///
      /// From android 8.0 onwards the GPS must be ON (high accuracy)
      /// in order to be able to obtain the SSID.
      Future<String?> getWifiName() {
        return _platform.getWifiName();
      }
    

    It returns a Future<String?> . You have two options here when it comes to your FutureBuilder

    Here is a demo of the default flutter app running this code on a mac app

    enter image description here

    You can either call it this way

    FutureBuilder<String?>(
          future: info.getWifiName(),
          builder: (context, snapshot) {
            if (snapshot.hasData &&
                snapshot.connectionState == ConnectionState.done) {
              return Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    const Text(
                      'You are connected to WIFI ',
                    ),
                    Text(
                      '${snapshot.data}',
                      style: Theme.of(context).textTheme.headline4,
                    ),
                  ],
                ),
              );
            }
            return const Center(
              child: CircularProgressIndicator(),
            );
          })
    

    or you can choose to not explicitly declare a data type when using FutureBuilder

    FutureBuilder(
          future: info.getWifiName(),
          builder: (context, snapshot) {
            if (snapshot.hasData &&
                snapshot.connectionState == ConnectionState.done) {
              return Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    const Text(
                      'You are connected to WIFI ',
                    ),
                    Text(
                      '${snapshot.data}',
                      style: Theme.of(context).textTheme.headline4,
                    ),
                  ],
                ),
              );
            }
            return const Center(
              child: CircularProgressIndicator(),
            );
          })
    

    Note that you aren't really converting the data type here, merely stating it and making the FutureBuilder aware of what data type to expect from the given future.