3 maneiras de cancelar um futuro em Flutter e Dart

Adquira o hábito de escrever juntos! Este é o 5º dia da minha participação no "Nuggets Daily New Plan · April Update Challenge", clique para ver os detalhes do evento .

3 maneiras de cancelar um futuro em Flutter e Dart

Autor: Nuts

Conta pública: " Big Front-End Tour "

Especialista em compartilhamento de nuvem da Huawei, autor do contrato InfoQ, blogueiro especialista em nuvem do Alibaba, diretor de experiência do blog 51CTO, um dos membros do projeto de código aberto GVA , com foco no compartilhamento de grandes tecnologias de front-end, incluindo Flutter, applet, Android, VUE , JavaScript.

Este artigo mostra 3 maneiras diferentes de cancelar futuros em Flutter e Dart.

Usar pacote assíncrono (recomendado)

O pacote assíncrono foi desenvolvido e publicado pelos autores da linguagem de programação Dart. Ele fornece utilitários de estilo dart:async para aprimorar a computação assíncrona. O que pode nos ajudar a cancelar um Future é a classe CancelableOperation :

var myCancelableFuture = CancelableOperation.fromFuture(
  Future<T> inner, 
  { FutureOr onCancel()? }
)
​
// call the cancel() method to cancel the future
myCancelableFuture.cancel();
复制代码

Para mais clareza, veja o exemplo real abaixo.

Exemplo completo

Visualização do aplicativo

animação 1

A aplicação que vamos construir tem um botão flutuante. Quando este botão é pressionado, uma operação assíncrona é iniciada (que leva 5 segundos para ser concluída). O fundo do botão mudou de índigo para vermelho, seu rótulo mudou de "Iniciar" para "Cancelar", e agora você pode usá-lo para cancelar o Futuro.

  • Se você clicar no botão Cancelar dentro de 5 segundos antes da conclusão do Futuro, a tela exibirá "Futuro cancelado".
  • Se você não fizer nada, a tela exibirá "Futuro concluído" após 5 segundos.

Uma demonstração vale mais que mil palavras:

código

1. Instale o pacote assíncrono fazendo o seguinte:

flutter pub add async
复制代码

Então corra:

flutter pub get
复制代码

2. Código fonte completo em main.dart (com explicação):

// main.dart
import 'package:flutter/material.dart';
import 'package:async/async.dart';
​
void main() {
  runApp(const MyApp());
}
​
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        // Remove the debug banner
        debugShowCheckedModeBanner: false,
        title: '大前端之旅',
        theme: ThemeData(
          primarySwatch: Colors.indigo,
        ),
        home: const HomePage());
  }
}
​
class HomePage extends StatefulWidget {
  const HomePage({Key? key}) : super(key: key);
​
  @override
  _HomePageState createState() => _HomePageState();
}
​
class _HomePageState extends State<HomePage> {
  // this future will return some text once it completes
  Future<String?> _myFuture() async {
    await Future.delayed(const Duration(seconds: 5));
    return 'Future completed';
  }
​
  // keep a reference to CancelableOperation
  CancelableOperation? _myCancelableFuture;
​
  // This is the result returned by the future
  String? _text;
​
  // Help you know whether the app is "loading" or not
  bool _isLoading = false;
​
  // This function is called when the "start" button is pressed
  void _getData() async {
    setState(() {
      _isLoading = true;
    });
​
    _myCancelableFuture = CancelableOperation.fromFuture(
      _myFuture(),
      onCancel: () => 'Future has been canceld',
    );
    final value = await _myCancelableFuture?.value;
​
    // update the UI
    setState(() {
      _text = value;
      _isLoading = false;
    });
  }
​
  // this function is called when the "cancel" button is tapped
  void _cancelFuture() async {
    final result = await _myCancelableFuture?.cancel();
    setState(() {
      _text = result;
      _isLoading = false;
    });
  }
​
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('大前端之旅')),
      body: Center(
        child: _isLoading
            ? const CircularProgressIndicator()
            : Text(
                _text ?? 'Press Start Button',
                style: const TextStyle(fontSize: 28),
              ),
      ),
      // This button is used to trigger _getDate() and _cancelFuture() functions
      // the function is called depends on the _isLoading variable
      floatingActionButton: ElevatedButton(
        onPressed: () => _isLoading ? _cancelFuture() : _getData(),
        child: Text(_isLoading ? 'Cancel' : 'Start'),
        style: ElevatedButton.styleFrom(
            padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 30),
            primary: _isLoading ? Colors.red : Colors.indigo),
      ),
    );
  }
}
​
复制代码

Usando o método timeout()

Este método é rápido e fácil. No entanto, não é muito flexível.

Usando o método timeout() , você pode limitar o tempo do Future (por exemplo, 3 segundos). Se o futuro for concluído a tempo, seu valor será devolvido. Por outro lado, se o Futuro ultrapassar o tempo limite, a função onTimeout será executada:

Future<T> timeout(
   Duration timeLimit,
  {FutureOr<T> onTimeout()?}
)
复制代码

Exemplo rápido

Crie um Futuro fictício:

Future<String?> _myFuture() async {
    await Future.delayed(const Duration(seconds: 10));
    return 'Future completed';
}
复制代码

Defina um tempo limite de 3 segundos:

_myFuture().timeout(
      const Duration(seconds: 3),
      onTimeout: () =>
          'The process took too much time to finish. Please try again later',
);
复制代码

Converter futuro em stream

Você pode usar o método asStream() da classe Future para criar um fluxo contendo os resultados brutos do Future. Agora você pode cancelar a inscrição neste fluxo.

Exemplo rápido

// don't forget to import this
import 'dart:async';
​
// Create a demo future
Future<dynamic> _loadData() async {
    await Future.delayed(const Duration(seconds: 10));
    return 'Some Data';
}
​
// a reference to the stream subscription
// so that we can call _sub.cancel() later
StreamSubscription<dynamic>? _sub;
​
// convert the future to a stream
_sub = _loadData().asStream().listen((data) {
    // do something with "data"
    print(data);
 });
​
// cancel the stream subscription
_sub.cancel();
复制代码

Observe que este exemplo rápido descreve apenas brevemente como as coisas funcionam. Você deve modificá-lo para funcionar em um projeto existente.

para concluir

Você aprendeu mais de uma maneira de cancelar um Future in Flutter. Escolha um deles para implementar em seu aplicativo para torná-lo mais robusto e atraente ao lidar com tarefas assíncronas.

Acho que você gosta

Origin juejin.im/post/7083506236112502814
Recomendado
Clasificación