簡體   English   中英

Flutter - 如何在不執行的情況下將未來傳遞給小部件?

[英]Flutter - How to pass a future to a widget without executing it?

我在我的一個小部件中使用 FutureBuilder,它需要一個未來。 我通過它的構造函數將未來傳遞給小部件。 問題在於,在將未來傳遞給小部件時,它會自動執行。 由於 FutureBuilder 只接受 Future 而不是 Future Function() 我被迫初始化一個變量,該變量又調用異步 function。 但我不知道如何在沒有被執行的情況下通過未來。

這是完整的工作示例:

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {

  final icecreamSource = DataService.getIcecream();
  final pizzaSource = DataService.getPizza();
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
     
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: Column(
            children: [
              MenuButton(label: 'Ice Cream', dataSource: icecreamSource),
              MenuButton(label: 'Pizza', dataSource: pizzaSource),
            ]
          ),
        ),
      ),
    );
  }
}


class MenuButton extends StatelessWidget {
  final String label;
  final Future<String> dataSource;
  
  const MenuButton({required this.label, required this.dataSource});
  
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(16.0),
      child: ElevatedButton(
        child: Text(label),
        onPressed: () => Navigator.push(context, MaterialPageRoute(builder: (context) => AnotherPage(label: label, dataSource: dataSource)))
      ),
    );
  }
}


// Mock service to simulate async data sources
class DataService {
  static Future<String> getIcecream() async {
    print('Trying to get ice cream...');
    return await Future.delayed(const Duration(seconds: 3), () => 'You got Ice Cream!');
  }
  
  static Future<String> getPizza() async {
    print('Trying to get pizza...');
    return await Future.delayed(const Duration(seconds: 2), () => 'Yay! You got Pizza!');
  }
}


class AnotherPage extends StatefulWidget {
  final String label;
  final Future<String> dataSource;
  const AnotherPage({required this.label, required this.dataSource});
  @override
  State<AnotherPage> createState() => _AnotherPageState();
}

class _AnotherPageState extends State<AnotherPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(widget.label)),
      body: Center(
        child: FutureBuilder<String>(
        future: widget.dataSource,
        builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
          if(snapshot.hasData) {
            return Text('${snapshot.data}');
          } else if(snapshot.hasError) {
            return Text('Error occurred ${snapshot.error}');
          } else {
            return Text('Fetching ${widget.label}, please wait...');
          }
        }
      ),
      ),
    );
  }
}

預期的行為是,當我按下主頁上的“冰淇淋”或“披薩”按鈕時,應該出現名為“另一個頁面”的小部件/屏幕,並且應該執行異步請求,在此期間應該顯示加載消息。 然而,正在發生的事情是在加載主頁時,甚至在按下任何按鈕之前,兩個異步請求都被執行。 在按下任何按鈕時,加載消息不會出現,因為請求已經完成,因此它直接顯示結果,這是完全不可取的。 我現在對 Futures 和 Future Functions 完全感到困惑。 有人請幫幫我。

而是通過 Future function,你為什么不嘗試傳遞一個字符串?

移除所有final Future<String> dataSource; . 你不需要它。

您只能使用label

.....
 body: Center(
   child: FutureBuilder<String>(
   future: widget.label == 'Pizza' 
            ?  DataService.getPizza() 
            :  DataService.getIcecream(),
   builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
....

我只是在https://dartpad.dev中測試它。 它的工作正常。 如果您可以通過簡單的方式實現,則不必復雜化。

而不是傳遞Future您可以傳遞 function 本身,它返回Future 你可以在DartPad上試試這個例子。

您必須像這樣修改MyApp

final icecreamSource = DataService.getIcecream; // No () as we want to store the function
final pizzaSource = DataService.getPizza; // Here aswell

MenuButtonAnotherPage中,我們需要:

final Future<String> Function() dataSource; // Instead of Future<String> dataSource

不,我們可以將未來直接傳遞給FutureBuilder ,但是讓 FutureBuilder 直接執行未來是不好的做法,因為構建方法被多次調用。 相反,我們有這個:

class _AnotherPageState extends State<AnotherPage> {
  late final Future<String> dataSource = widget.dataSource(); // Gets executed right here
  ...
}

現在我們可以將這個未來傳遞給未來的構建者。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM