'Flutter - location permissions not being asked when using future builder

I am using location plugin to get user location in background.

The build of app is dependent on a future value where it first checks in initState if user is registered using a REST API, and poll location if user is registered or show Register button.

Below is relevant structure my code:


class HomePage extends StatefulWidget {
  const HomePage ({Key? key}) : super(key: key);
  @override
  State<StatefulWidget> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {

  Location location = Location();

  Future<bool>? _registered;
  late bool _serviceEnabled;
  late PermissionStatus _permissionGranted;
  late LocationData _locationData;

  Future<bool> fetchUserInfo() async {
    // checks if user is registered
  }

  Future<LocationData?> setLocationPermissions() async {
    _serviceEnabled = await location.serviceEnabled();
    if (!_serviceEnabled) {
      _serviceEnabled = await location.requestService();
      if (!_serviceEnabled) {
        return null;
      }
    }

    _permissionGranted = await location.hasPermission();
    if (_permissionGranted == PermissionStatus.denied) {
      _permissionGranted = await location.requestPermission();
      if (_permissionGranted != PermissionStatus.granted) {
        return null;
      }
    }

    await location.changeSettings(interval: 30000);
    await location.enableBackgroundMode(enable: true);

    _locationData = await location.getLocation();
    return _locationData;
  }

  @override
  void initState() {
    setLocationPermissions().then((value) {
      _locationData = value!;
    }); //this is supposed to ask for location permissions

    // Fetch user details from server
    _registered = fetchUserInfo();

    location.onLocationChanged.listen((LocationData currentLocation) {
      // do more stuff
    });

    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final Size screenSize = MediaQuery.of(context).size;

    return Scaffold(
      appBar: AppBar(
        title: const Text('Manager'),
      ),
      body: FutureBuilder(
        future: _registered,
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            return _buildWidget(screenSize); // widget function that returns either a 
                                             // Register button or Text "You are registered"
                                             // based on another value set in fetchUserInfo
          } else if (snapshot.hasError){
            Fluttertoast.showToast(msg: snapshot.error.toString());
            return const SizedBox();
          } else {
            return Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: const <Widget>[
                  CircularProgressIndicator(),
                ],
              ),
            );
          }
        }
      ),
    );
  }
}

When I open the app on release apk, if a user is not registered it simply renders the register button from _buildWidget. My expectation is that it should ask for location permission based on code in initState. However it doesn't. It was working fine if I don't use a FutureBuilder (here)



Solution 1:[1]

Possible problem is that widget build up is somehow over-riding the locations popup or its future never makes it to user interface due to some error in setpermissions initialization or some conflict with widget tree..

I fixed it by putting all the code inside initState in one common async function and setting the future of the future builder to this common function.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 MohitC