将异步数据(GPS 协调)从 FutureBuilder 传递给提供者/设置异步构造函数

Posted

技术标签:

【中文标题】将异步数据(GPS 协调)从 FutureBuilder 传递给提供者/设置异步构造函数【英文标题】:Passing async data (GPS coordination) from FutureBuilder to Provider / Setting async constructor 【发布时间】:2020-04-22 15:16:18 【问题描述】:

我在处理async 数据(即用户 GPS 协调)输入时遇到问题。

我将我的应用程序简化为下面的计算器应用程序,它通过provider 管理状态(双精度)。

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() => runApp(ProviderApp());

class ProviderApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return ChangeNotifierProvider<MyProvider>(
      create: (_) => MyProvider(1.55),
      child: CalApp(),
    );
  


class CalApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    final myProvider = Provider.of<MyProvider>(context);

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(myProvider.getMyProvider().toString()),
              RaisedButton(
                child: Text('increase 10%'),
                onPressed: () 
                  myProvider.userProvider();
                ,
              )
            ],
          ),
        ),
      ),
    );
  


class MyProvider with ChangeNotifier 
  double _myProvider;
  MyProvider(this._myProvider);

  double getMyProvider() => _myProvider;

  void userProvider() 
    _myProvider *= 1.1;
    notifyListeners();
  

现在我不想使用初始的double 1.55,而是使用用户当前的纬度作为Geolocator 的一次性输入。

1) 我的第一个解决方案是通过FutureBuilder 将纬度向下传递到ProviderApp

这有点工作,但在获得最后一页之前,有一个错误页面显示 FutureBuilder 正在传递 null

如果我给 FutureBuilder 一个 initialData: Position(latitude: 20.0),,那么提供者将只取 20.0 并忽略以下纬度数据。

import 'dart:ffi';
import 'dart:async';
import 'package:geolocator/geolocator.dart';

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() => runApp(TreeTop());

class TreeTop extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    Gps gps = Gps();

    return FutureBuilder(
      future: gps.currentPosition,
      // initialData: Position(latitude: 20.0),
      builder: (context, snapshot) 
        return ProviderApp(snapshot.data.latitude);
      ,
    );
  


class ProviderApp extends StatelessWidget 
  final double myNum;
  ProviderApp(this.myNum);
  @override
  Widget build(BuildContext context) 
    return ChangeNotifierProvider<MyProvider>(
      create: (_) => MyProvider(myNum),
      child: CalApp(),
    );
  


class CalApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    final myProvider = Provider.of<MyProvider>(context);

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(myProvider.getMyProvider().toString()),
              RaisedButton(
                child: Text('increase 10%'),
                onPressed: () 
                  myProvider.userProvider();
                ,
              )
            ],
          ),
        ),
      ),
    );
  


class MyProvider with ChangeNotifier 
  double _myProvider;
  MyProvider(this._myProvider);

  double getMyProvider() => _myProvider;

  void userProvider() 
    _myProvider *= 1.1;
    notifyListeners();
  


class Gps 
  //
  // get * one-time * user coordination via geolocator
  //
  Future<Position> currentPosition = Geolocator().getCurrentPosition(
      desiredAccuracy: LocationAccuracy.bestForNavigation,
      locationPermissionLevel: GeolocationPermission.locationWhenInUse);

2) 然后在from Setting provider value in FutureBuilder 寻找 Rémi Rousselet 的解决方案, 我尝试修改 MyProvider 构造函数但失败了,因为我无法使构造函数异步。

3) 现在我正在考虑将FutureProvider 注入ChangeNotifierProvider,但我真的很怀疑。

在这一点上,我觉得我在与框架和包作斗争,而不是让它们帮助我,所以我希望你能给我一些建议。

【问题讨论】:

【参考方案1】:

睡了一会儿,感觉可以通过查看snapshot.data简单解决

        return snapshot.hasData
            ? ProviderApp(snapshot.data.latitude)
            : Center(child: CircularProgressIndicator());

【讨论】:

以上是关于将异步数据(GPS 协调)从 FutureBuilder 传递给提供者/设置异步构造函数的主要内容,如果未能解决你的问题,请参考以下文章

国际原子时(TAI),GPS时间,协调世界时(UTC)以及rinex文件起止时间

国际原子时协调世界时世界时和GPS时间系统之间的关系

异步服务器设计

国际原子时世界时协调时GPS时

国际原子时世界时协调时GPS时

Google Maps API:使用 GPS 纬度经度协调器在地图上显示标记