繁体   English   中英

如何将 Future builder 与提供者一起使用?

[英]How can I use Future builder with provider?

我的主要目标是在获得位置地址placename之前显示一个CircularProgressIndicator但我不断收到此错误The getter 'placeName' was called on null. .我确实尝试检查futureBuilder中的null值,但我相信我的实现是错误的。 你能看看吗? 这是我的AppData

class AppData extends ChangeNotifier {
 Address pickUpLocation;
 void updatePickUpLocationAddress(Address pickUpAddress) {
    pickUpLocation = pickUpAddress;
    notifyListeners();
  }
}

这是Address

class Address {
  String placeFormattedAddress;
  dynamic placeName;
  String placeId;
  double latitude;
  double longitude;

  Address(
      {this.placeFormattedAddress,
      this.placeName,
      this.placeId,
      this.latitude,
      this.longitude});
}

现在在我的MainScreen中,我像这样使用它,但错误仍然存​​在。

 @override
  Widget build(BuildContext context) {
\\\
body: Stack( 
\\\
Flexible(
    child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
            FutureBuilder (
                future: Provider.of < AppData > (context)
                .pickUpLocation
                .placeName,
                builder: (context, snapshot) {
                    if (snapshot.data == null) {
                        return CircularProgressIndicator();
                    } else {
                        return Text(
                            Provider.of < AppData > (context)
                            .pickUpLocation
                            .placeName,

                            style: TextStyle(fontSize: 12.0),
                            overflow: TextOverflow.ellipsis,
                            
                        );
                    }
                }),
          
        ],
    ),
)

有几件事需要注意。

  1. 您的 getter 不会返回Future并且它没有被写入这样做。 发生的情况是您的pickUpLocation = pickUpAddress表达式会立即被评估,因为它是一个同步操作,即Future转换为实际值之前。
  2. 您正在使用Provider来返回您正在寻找的Future (这很好),但是这样做是错误的,因为它基本上会“弄乱”您的 Widget 树:假设您的 ProviderFuture 有更新已完成:应该先渲染哪个子树?

要解决您的情况,您必须:

  1. 让您的吸气剂正确返回并处理Future
  2. 在调用 build 方法之前初始化对 getter 的调用(即 Future 调用),以便:
    • 上述问题消失;
    • 您不会遇到另一个经典问题:在每次 UI 重新构建时调用 Future(例如发送后端请求)。

以下是我将如何更改您的提供者模型/类:

class AppData extends ChangeNotifier {
 Address? pickUpLocation;

 Future<void> updatePickUpLocationAddress() async {
    // There should be error handling, as well (try-catch-finally clauses)
    var pickUpLocation = await Future.delayed(Duration(seconds: 5));  // I'm mocking a request, here
    
    notifyListeners();
  }
}

现在,要初始化 Future,您可以在上面的 Provider 中(在AppData的构造函数中)执行此操作,或者您必须将 Widget 更改为Stateful以便我们可以访问initState()方法,在该方法中我们可以初始化未来无需担心多次调用。 在您的(现在Stateful的)小部件中:

var myFuture;
// ...
void initState() {
  myFuture = Provider.of<AppData>(context).updatePickUpLocationAddress();
}
// ...
Widget build (BuildContext context) {
  return // ...
         FutureBuilder(
           future: myFuture, // already initialized, won't re-initalize when build() is called
           builder: (ctx, snapshot) => // ...
}
Flexible(
        child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
                if (Provider.of < AppData > (context)
                    .pickUpLocation ==
                    null)
                    CircularProgressIndicator(),

                    if (Provider.of < AppData > (context)
                        .pickUpLocation !=
                        null)
                        Text(
                            Provider.of < AppData > (context)
                            .pickUpLocation
                            .placeName,
                            style: TextStyle(fontSize: 12.0),
                            overflow: TextOverflow.ellipsis,
                        ),
                      ),  
                     )  

对于遇到此问题的任何人,您可以轻松地在 Mac 上单击 Options+enter,然后单击“使用 Builder 包装”,然后将上下文传递给您未来的函数

 child: Builder(
                builder: (context) {
                  return FutureBuilder(
                      future: futureFunctionHere(context),
                      builder: (context, AsyncSnapshot snapshot) {

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM