Flutter进阶-Future、FutureBuilder、StreamBuilder详解

一、时间循环 Event Loop机制

程序之所以卡说白了就是没有时间更新UI界面刷新屏幕导致

常见的卡顿主要是两种:

1.很大的计算量CPU忙不过来

2.等待,等服务器的响应、等用户的输入、等文件的读取...等等

在多线程的机制里每当遇到需要等的东西就开启一个新的线程去守着,负责更新UI的主线程就不会挂起就不会感到卡顿。

但是在Dart中,每个线程都是被封装在Isolate中,每个Isolate是被孤立的隔离开的,彼此不共享内存,彼此间通过发消息来进行通讯

直接运行 Microtask Event

Future.sync()

scheduleMicrotask()

Future()

Future.value()

Future.microtask()

Future.delayed()

_.then() _completed.then()

二、FutureBuilder 

通过监听传递的future值的变化进行刷新界面(而不需要使用setState)

 @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text(''),
      ),
      body: FutureBuilder(
        initialData: "haha",
          future:
              Future.delayed(const Duration(seconds: 2), () => throw ('error')),
          builder: (context, snapshot) {
            if (snapshot.hasError) {
              return const Icon(Icons.error);
            }
            if (snapshot.hasData) {
              return Text("${snapshot.data}");
            }
            return const CircularProgressIndicator();
          }),
    );
  }

三、Stream与StreamBuilder

future只会打印一次,而Stream会持续不断的执行打印

 final future = Future.delayed(const Duration(seconds: 2), () => 40);
 final stream = Stream.periodic(const Duration(seconds: 1), (_) => 42);


 void test() {
    future.then((value) => print('future completed: $value'));
    stream.listen((event) {
      print("stream: $event");
    });
  }

 @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text(''),
        ),
        body: StreamBuilder(
            stream: stream,
            builder: (context, snapshot) {
              switch (snapshot.connectionState) {
                case ConnectionState.none:
                  return const Text("none: 没有数据");
                case ConnectionState.waiting:
                  return const Text("waiting: 等待数据流");
                case ConnectionState.active:
                  if (snapshot.hasError) {
                    return Text("active: 错误${snapshot.error}");
                  } else {
                    return Text("active: 正常${snapshot.data}");
                  }
                case ConnectionState.done:
                  return const Text("active: 数据流已经关闭");
              }
            }));
  }

StreamController更加方便的管理stream 

final StreamController streamController = StreamController();
  
@override
  void dispose() {
    streamController.close();
    super.dispose();
  }

  @override
  void initState() {
    super.initState();
    streamController.sink.add(72);
    streamController.stream.listen((event) {});
  }

  final StreamController streamController = StreamController();
  int count = 10;

  DefaultTextStyle(
                style: Theme.of(context).textTheme.headline4!,
                child: Column(children: [
                  RaisedButton(
                      child: const Text('10'),
                      onPressed: () {
                        count += 10;
                        streamController.sink.add(count);
                      }),
                  StreamBuilder(
                      stream: streamController.stream,
                      builder: (context, snapshot) {
                        switch (snapshot.connectionState) {
                          case ConnectionState.none:
                            return const Text("none: 没有数据");
                          case ConnectionState.waiting:
                            return const Text("waiting: 等待数据流");
                          case ConnectionState.active:
                            if (snapshot.hasError) {
                              return Text("active: 错误${snapshot.error}");
                            } else {
                              return Text("active: 正常${snapshot.data}");
                            }
                          case ConnectionState.done:
                            return const Text("active: 数据流已经关闭");
                        }
                      })
                ]));

 如果被多次监听会报错streamController.stream.listen((event) {});,确实需要可以使用final StreamController streamController = StreamController.broadcast();变成广播

实例:

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final _controller = StreamController();
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: StreamBuilder(
            stream: _controller.stream,
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                return Text("你输入了: ${snapshot.data.toString()}",
                    style: const TextStyle(
                        fontSize: 24, fontWeight: FontWeight.bold));
              }
              return const Text("等待...");
            }),
      ),
      body: Stack(children: [
        Puzzle(inputStream: _controller.stream),
        Align(
            alignment: Alignment.bottomCenter,
            child: KeyPad(controller: _controller))
      ]
      ),
    );
  }
}

class KeyPad extends StatelessWidget {
  final StreamController controller;
  const KeyPad({Key? key, required this.controller}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return GridView.count(
        shrinkWrap: true,
        childAspectRatio: 2 / 1,
        crossAxisCount: 3,
        mainAxisSpacing: 10,
        crossAxisSpacing: 10,
        children: List.generate(
            9,
            (index) => FlatButton(
                shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(10)),
                color: Colors.primaries[index][200],
                onPressed: () {
                  controller.add(index + 1);
                },
                child: Text(
                  "${index + 1}",
                  style: const TextStyle(fontSize: 24),
                ))));
  }
}

class Puzzle extends StatefulWidget {
  final Stream inputStream;
  const Puzzle({Key? key, required this.inputStream}) : super(key: key);

  @override
  State<Puzzle> createState() => _PuzzleState();
}

class _PuzzleState extends State<Puzzle> with SingleTickerProviderStateMixin {
  late int a, b;
  late Color color;

  late AnimationController _controller; //显示动画

  reset() {
    a = Random().nextInt(5) + 1;
    b = Random().nextInt(5);
    color = Colors.primaries[Random().nextInt(Colors.primaries.length)];
  }

  @override
  void initState() {
    reset();
    _controller =
        AnimationController(vsync: this, duration: const Duration(seconds: 10))
          ..forward();
    _controller.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        reset();
        _controller.forward(from: 0.0);
      }
    });
    widget.inputStream.listen((input) {
      if (input == a + b) {
        _controller.forward(from: 0.0);
      }
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
        animation: _controller,
        builder: (context, _) {
          return Positioned(
            top: 400 * _controller.value,
            left: 200 * _controller.value,
            child: Container(
              decoration: BoxDecoration(
                  color: color,
                  border: Border.all(color: Colors.black),
                  borderRadius: BorderRadius.circular(24)),
              padding: const EdgeInsets.all(5),
              child: Text(
                "$a + $b",
                style: const TextStyle(fontSize: 24),
              ),
            ),
          );
        });
  }
}

猜你喜欢

转载自blog.csdn.net/RreamigOfGirls/article/details/131164963
今日推荐