flutter开发核心 Future/stream/bloc

Future(异步操作)

  Future有三种状态未完成完成带有值完成带有异常,使用Future可以简化事件任务。Dart中,可以使用Future对象来表示异步操作的结果,Future返回类型是Future

有三种方法处理Future的结果:

  • then: 处理操作执行结果或者错误并返回一个新的Future
  • catchError: 注册一个处理错误的回调
  • whenComplete:类似final,无论错误还是正确,Future执行结束后总是被调用

    使用then来回调,场景使用:UI需要接口的数据,一些异步执行函数

# demo1
main() {
  Future f1 = new Future(() {
    print("我是第一个");
  });
  f1.then((_) => print("f1 then"));
  print("我是main");
}
# print:
# 我是main
# 我是第一个
# f3 then

Future和async/await结合使用

   使用链式调用的方式把多个future连接在一起,会严重降低代码的可读性。使用async和await关键字实现异步的功能。async和await可以帮助我们像写同步代码一样编写异步代码

Future getStr()async{
  var str = HttpRequest.getString('www.fgyong.cn');
  return str;
}

使用http请求地址www.fgyong.cn获取数据,然后返回。如何接收文本呢?

其实很简单,只需要使用await关键字即可,用来注册then回调。

main(List args) async {
  String string = await getStr();
  print(string);
}

等同于

main(List args) async {
  getStr().then((value) {
    print(value);
  });
}

stream—连续异步操作

如果Future表示单个计算的结果,则流是一系列结果

侦听流以获取有关结果(数据和错误)以及流关闭的通知。还可以在收听流时暂停播放或在流完成之前停止收听。

可以说Future 用于处理单个异步操作Stream 用来处理连续的异步操作。

Stream 分单订阅流和广播流。

单订阅流在发送完成事件之前只允许设置一个监听器,并且只有在流上设置监听器后才开始产生事件,取消监听器后将停止发送事件。即使取消了第一个监听器,也不允许在单订阅流上设置其他的监听器。广播流则允许设置多个监听器,也可以在取消上一个监听器后再次添加新的监听器。

Stream 有同步流和异步流之分。

它们的区别在于同步流会在执行 addaddError 或 close 方法时立即向流的监听器 StreamSubscription 发送事件,而异步流总是在事件队列中的代码执行完成后在发送事件。

在 Dart 有几种方式创建 Stream

  1. 使用 async* 函数,函数标记为 async *,我们可以使用 yield 作为关键字并返回 Stream 数据
  2. 从现有的生成一个新的流 Stream,使用 mapwheretakeWhile 等方法。
    Stream countStream(int to) async* {
      for (int i = 1; i <= to; i++) {
        yield i;
      }
    }
    
    Stream stream = countStream(10);
    stream.listen(print);
  3. 使用 StreamController
    StreamController _streamController = StreamController(
      onCancel: () {},
      onListen: () {},
      onPause: () {},
      onResume: () {},
      sync: false,
    );
    
    Stream _stream = _streamController.stream;
  4. 使用 Future 对象生成
    Future _delay(int seconds) async {
      await Future.delayed(Duration(seconds: seconds));
      return seconds;
    }
    
    List futures = [];
    for (int i = 0; i < 10; i++) {
      futures.add(_delay(3));
    }
    
    Stream _futuresStream = Stream.fromFutures(futures);

我们在实际的开发过程中,基本都是使用的StreamContoller来创建流。监听使用StreamBuilder,当流发生变化时执行,例子:

import 'dart:async';
import 'package:flutter/material.dart';

class StreamCounter extends StatefulWidget {
  @override
  _StreamCounterState createState() => _StreamCounterState();
}

class _StreamCounterState extends State {
  // 创建一个 StreamController
  StreamController _counterStreamController = StreamController(
    onCancel: () {
      print('cancel');
    },
    onListen: () {
      print('listen');
    },
  );

  int _counter = 0;
  Stream _counterStream;
  StreamSink _counterSink;

  // 使用 StreamSink 向 Stream 发送事件,当 _counter 大于 9 时调用 close 方法关闭流。
  void _incrementCounter() {
    if (_counter > 9) {
      _counterSink.close();
      return;
    }
    _counter++;
    _counterSink.add(_counter);
  }

  // 主动关闭流
  void _closeStream() {
    _counterStreamController.close();
  }

  @override
  void initState() {
    super.initState();
    _counterSink = _counterStreamController.sink;
    _counterStream = _counterStreamController.stream;
  }

  @override
  void dispose() {
    super.dispose();
    _counterSink.close();
    _counterStreamController.close();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Stream Counter'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('You have pushed the button this many times:'),
            // 使用 StreamBuilder 显示和更新 UI
            StreamBuilder(
              stream: _counterStream,
              initialData: _counter,
              builder: (context, snapshot) {
                if (snapshot.connectionState == ConnectionState.done) {
                  return Text(
                    'Done',
                    style: Theme.of(context).textTheme.bodyText2,
                  );
                }

                int number = snapshot.data;
                return Text(
                  '$number',
                  style: Theme.of(context).textTheme.bodyText2,
                );
              },
            ),
          ],
        ),
      ),
      floatingActionButton: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          FloatingActionButton(
            onPressed: _incrementCounter,
            tooltip: 'Increment',
            child: Icon(Icons.add),
          ),
          SizedBox(width: 24.0),
          FloatingActionButton(
            onPressed: _closeStream,
            tooltip: 'Close',
            child: Icon(Icons.close),
          ),
        ],
      ),
    );
  }
}

bloc—状态管理

上文了解到stream,是使用bloc的必要知识。bloc的一个基础使用是CubitCubit类似是bloc的简化版,在一些小的项目上可以使用Cubit。项目维护的数据多使用Bloc最好,下面写的是bloc核心知识和使用案例

bloc处理关系图:

flutter开发核心 Future/stream/bloc_第1张图片

  • Bloc模式
    • bloc:逻辑层
    • state:数据层
    • event:所有的交互事件
    • view:页面

Bloc模板

  • view:默认添加了一个初始化事件
class CounterPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (BuildContext context) => CounterBloc()..add(InitEvent()),
      child: Builder(builder: (context) => _buildPage(context)),
    );
  }

  Widget _buildPage(BuildContext context) {
    final bloc = BlocProvider.of(context);

    return Container();
  }
}
  • bloc
class CounterBloc extends Bloc {
  CounterBloc() : super(CounterState().init());

  @override
  Stream mapEventToState(CounterEvent event) async* {
    if (event is InitEvent) {
      yield await init();
    }
  }

  Future init() async {
    return state.clone();
  }
}
  • event
abstract class CounterEvent {}

class InitEvent extends CounterEvent {}

  • state
class CounterState {
  CounterState init() {
    return CounterState();
  }

  CounterState clone() {
    return CounterState();
  }
}

你可能感兴趣的:(移动开发,flutter,dart,bloc)