【问题标题】:Flutter - Stop FutureBuilder operation in between processFlutter - 在进程之间停止 FutureBuilder 操作
【发布时间】:2021-07-04 19:57:43
【问题描述】:

重建小部件时如何取消FutureBuilder操作

假设我有这样的代码...每次我按下浮动按钮时,小部件都会重建调用 myFuture 等待五秒钟然后计数器增加...现在我想要在那五秒钟内,如果我按下浮动按钮,当前的 Future(仍然延迟)应该 停止其操作 并且新的 Future 将被调用...所以最后我应该得到一个 2 的计数器,但我得到了3...

class MyHomePage extends StatefulWidget {

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  var counter = 0;
  
  myFuture()async{
    await Future.delayed(Duration(seconds:5));
    counter++;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      body: FutureBuilder(
        future: myFuture(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting)
            return Center(child: CircularProgressIndicator());
          else return Text(counter.toString());
        }
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: ()=>setState(() {}),
        child: Icon(Icons.add),
      ),
    );
  }
}
 

【问题讨论】:

    标签: flutter dart


    【解决方案1】:

    或者,如果适合您的用例,您也可以使用 StreamStreamBuilder 代替 FutureFutureBuilder

    void main() {
      // keep a reference to your stream subscription
      StreamSubscription<List> dataSub;
      
      // convert the Future returned by getData() into a Stream
      dataSub = getData().asStream().listen((List data) {
        updateDisplay(data);
      });
    
      // user navigated away!
      dataSub.cancel();
    }
    

    来源:https://dart.academy/how_cancel_future/

    【讨论】:

      【解决方案2】:

      要取消 Future,您可以使用 async 包中的 CancelableOperation

      它的实现如下所示:

        Future<dynamic> executeCancelable(Future<dynamic> futureMethod) async {
          operation?.cancel();
          operation = CancelableOperation.fromFuture(futureMethod, onCancel: () {
            print('Future stopped');
          });
      
          return operation.value;
        }
      
        Future<dynamic> futureMethod() async {
          return Future.delayed(const Duration(milliseconds: 3000), () {
            return counter++;
          });
        }
      

      可以通过以下方法调用:

      executeCancelable(futureMethod())
      

      请注意,在此示例中,我使用的是 Future.delayed,它不能“真正”被取消为 explained here
      例如,这个 sn-p 可以很好地与 API 查询配合使用。

      【讨论】:

      • 没有取消Future的通用机制;这不是特定于Future.delayed。充其量您可以设置一个标志并让Future 计算检查它以提前退出。 CancelableOperation 所做的只是防止触发完成回调;它不会停止 Future 的计算本身的执行。
      【解决方案3】:
      int counter = 0;
      
        fiveSeconds() async {
          await Future.delayed(Duration(seconds: 5));
        
        }
      
          twoSeconds() async {
          await Future.delayed(Duration(seconds: 2));
          
        }
      
         bool _futureTime = true; 
      
       @override
        Widget build(BuildContext context) {
          return Scaffold(
            appBar: AppBar(),
            body: FutureBuilder(
              future: _futureTime ? fiveSeconds() : twoSeconds(),
              builder: (context, snapshot) {
                if (snapshot.connectionState == ConnectionState.waiting)
                  return Center(child: CircularProgressIndicator());
                else counter++;
           return Text(counter.toString());
              }
            ),
            floatingActionButton: FloatingActionButton(
              onPressed: (){setState(() {
             _futureTime = !_futureTime;
              });
              },
              tooltip: 'Increment',
              child: Icon(Icons.add),
            ),
          );
        }
      }
      

      【讨论】:

      • 我的代码与计数器无关..这只是一个例子......我想要的是..取消调用setstate时仍在运行的未来函数跨度>
      • 我编辑了我的答案,将你的逻辑移到 Future.dalyed 之外,并在未来的构建器中运行它,即counter++。它会起作用的。
      • 假设我的函数中有 3 个FutureDelayed .. 并且在每个 FutureDelay 之后它都会做一些事情......所以如果它在第二次延迟并且我按下了浮动按钮......第三次延迟根本不应该运行......
      • @thenoobslayer 你的意思是,如果你说 3 个期货(都延迟 5 秒),当 future1 正在运行并且你按下 FAB 时,它应该取消 future1 并运行 future2,如果再次按下 FAB ,future2应该被取消,future3应该在5s后运行并执行操作?
      猜你喜欢
      • 2021-08-15
      • 2020-02-06
      • 1970-01-01
      • 2020-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-02
      • 2015-04-06
      相关资源
      最近更新 更多