dart Flutter -使用future builder时不询问位置权限

ghhaqwfi  于 2023-05-04  发布在  Flutter
关注(0)|答案(2)|浏览(137)

我正在使用location插件在后台获取用户位置。
应用程序的构建取决于未来的值,如果用户使用REST API注册,则首先检查initState,如果用户注册或显示Register按钮,则轮询位置。
下面是我的相关结构代码:

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(),
                ],
              ),
            );
          }
        }
      ),
    );
  }
}

当我在release apk上打开应用程序时,如果用户没有注册,它只会从_buildWidget呈现注册按钮。我的期望是它应该基于initState中的代码请求位置权限。但事实并非如此。如果我不使用FutureBuilder(here),它工作得很好。

6yt4nkrj

6yt4nkrj1#

可能的问题是,小部件的建立是以某种方式覆盖位置弹出或其未来永远不会使它的用户界面,由于一些错误,在设置权限初始化或一些冲突与小部件树。
我通过将initState中的所有代码放在一个公共异步函数中并将未来构建器的future设置为这个公共函数来修复它。

zzzyeukh

zzzyeukh2#

您没有获得位置权限,因为在您的initState中调用了一些异步事件。Flutter生命周期告诉我们,虽然initState先运行,但任何异步事件的运行都需要时间。这就是为什么即使你的函数在initState中首先被调用,但由于它们是异步的,小部件构建方法首先被触发,因此它覆盖了你的位置权限弹出窗口。
要解决这个问题,您可以将另一个futureBuilder Package 到当前的futureBuilder。第一个futureBuilder应该有位置权限任务,第二个futureBuilder应该有_registered任务。

相关问题