如何在需要 BuildContext 的 future 中使用 FutureBuilder,而无需在 Flutter 中的每个构建中重新计算 Future? [重复]

问题描述 投票:0回答:3

我正在使用 Flutter 并尝试使用 FutureBuilder 根据 Provider 包管理的状态来获取数据。我面临的挑战是我的未来取决于我可以通过

Provider.of<MyData>(context)
进入的状态。

问题来了:

  1. 我需要在小部件的构造函数中初始化 Future,但由于构造函数无权访问构建上下文,因此我无法从提供程序检索状态。
  2. 如果我尝试在构建方法中创建 Future,每次小部件重建时都会重新计算,这对于性能来说并不理想。

我目前的方法:

class MyWidget extends StatelessWidget {
  final Future<DataType> future;

  MyWidget() : future = fetchData(); // This can't access context

  @override
  Widget build(BuildContext context) {
    final myData = Provider.of<MyData>(context); // Need to use myData here

    // Creating the Future here causes it to recompute on every build
    final future = fetchDataBasedOn(myData);

    return FutureBuilder<DataType>(
      future: future,
      builder: (context, snapshot) {
        // Build your widget based on snapshot
      },
    );
  }
}

我的问题: 我如何以只计算一次的方式管理 Future,并且仍然能够访问提供者的状态?是否有推荐的模式可以使用 Flutter 的 FutureBuilder 和 Provider 来实现这一目标?

任何建议或示例将不胜感激!

flutter dart
3个回答
1
投票

可以使用initState,initState仅用于在创建widget时初始化Future一次。

示例:

Future<DataType>? future;

void initState() {
    super.initState();

    WidgetsBinding.instance.addPostFrameCallback((callback) {
      final data = Provider.of<YourProvider>(context);
      setState(() {
        future = fetchData(data);
      });
    });
  }

然后在您使用的 FutureBuilder 中使用 future


1
投票
 class MyWidget extends StatefulWidget {
  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  Future<DataType> future;

@override
  void didChangeDependencies() {
super.didChangeDependencies();
// Initialize the future in 

didChangeDependencies
    future = fetchDataBasedOn(Provider.of<MyData>(context, listen: false));
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<DataType>(
      future: future,
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return CircularProgressIndicator();
        } else if (snapshot.hasError) {
          return Text('Error: ${snapshot.error}');
        } else {
          return Text('Data: ${snapshot.data}');
        }
      },
    );
  }
}

你可以这样使用,希望对你有帮助。


0
投票
    > you can use init() method to manage future and  it compute only once and also you can access provider state.
    
- example for understanding..
    
     /// Create getter and future variable
        Demo get demoData => Provider.of(context, listen: false);
        late Future<dynamic> future;
        
    /// call getData() method 
        void initState() {
         super.initState();
         getData();
       }
    
     /// in this method you can initialized futureVariable and also manage provider state and you can use future in futureBuilder alse
        getData() async {
          future = await fetchData(demoData);
        }
© www.soinside.com 2019 - 2024. All rights reserved.