flutter的future,futureBilder,StreamBuilder,key的了解



csdn博客文章NO.6

前言

          今天在b站上面意外有个发现,昨天在学习flutter的时候,我就发现这个讲视频的老师水平可以,他的up名叫做 “王叔不秃”,没有丝毫的卡壳,讲的非常的明白。我就好奇了,flutter才出来多久,怎么就这么了解。就在看视频的时候不经意间看到,原来人家是硅谷的高级工程师😥😥😥。讲的大多数是一些重点和难点,比如动画效果啊,Stream流,异步这些东西。那么今天我也就讲讲我今天了解到的一些东西


一、单线程中的future是怎么运行的

我们都知道dart语言和javaScript类似,都是单线程。future首先是基于监听循环机制evntloop ,来做异步处理。异步分为三种级别,第一种是直接执行的,第二种是处理一些比较特殊的 任务,第三中是我们一般所用到的

                       Future.sync(),
   直接执行             Future.value(), 
                       _.then(),

                       scheduleMicarotask()
  Micarotask           Future.microtask()
                       _completed.then()

                       Future()
   Event               Future.delayed()

编写一下代码打印

void main(){
  scheduleMicrotask(() => print("Microtash 1"));
  Future.microtask(() => print("Microtash 2"));
  Future.value(123).then((value) => print("Microtash 3"));

  Future((){print("future 1");});
  print("main 1");
  Future.sync(() => print("sync 1"));
  print("main 2");

  Future.delayed(Duration(seconds: 1),()=>print("delayed"))
      .then((value){
      scheduleMicrotask(()=>print("micro"));
      print("then");
  }).then((value) => print("then 2"));

  getFuture().then((value) => print("get function"))
      .catchError((e) => print(e))
      .whenComplete(() => print("final"));

}

Future getFuture()async{
  return Future.error("Invoking is error function");
}

二, FutureBuilder的使用

使用FutureBuilder的好处,在我们的实际工作中,是需要调用后台的接口。在调用的过程中,需要使用到异步的方法。futureBuilder有个future属性我调用异步之后,获取到的不管是数据还好或者是错误信息,null之类的都能帮助我们很好的处理之后再渲染到页面上去。

 import 'package:flutter/material.dart';

class FutureBuilderDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: FutureBuilder(
           //获取数据有个等待的时候
            future: Future.delayed(Duration(seconds: 2),()=>throw "440"),        
            builder: (BuildContext context,AsyncSnapshot<dynamic> snapshot)
             //如果错误了,就是一个错误的icon
              if(snapshot.hasError){
                return Icon(Icons.error,size: 80);
              }
              //如果有数据就渲染到页面上面去
              if(snapshot.hasData){
                return Text("${snapshot.data}",style: TextStyle(fontSize: 80));
              }
              //如果上面的条件都没有执行,就说明数据还没有获取到,执行的是一直转圈圈的动画
              return CircularProgressIndicator();
            }
        ),
      ),
    );
  }
}

三、StreamBuller的使用

StreamBuller是基于流的一种概念,流的概念是什么?就是有源头的资源获取,当我往源头里面放进去一个东西,相应的我就可以得到一个东西,放东西的动作时sink.add(“增加数据”),取东西要从 builder: (BuildContext context, AsyncSnapshot snapshot)里面的snapshot获取。
流只能被一个人监听,如果要被多个人监听就得使用广播的形式。如果一但使用广播的形式,里面的数据就不能被缓存起来

代码如下(示例):

import 'dart:async';

import 'package:flutter/material.dart';

///  数据流只能被一个人监听,如果要多个人监听怎要开启广播模式
///  广播数据流是不会缓存起来的
///

class StreamBuilderDemo extends StatefulWidget {
  @override
  _StreamBuilderDemoState createState() => _StreamBuilderDemoState();
}

class _StreamBuilderDemoState extends State<StreamBuilderDemo> {
  StreamController _controller;

  @override
  void initState() {
    super.initState();
    //开启广播模式
    _controller = new StreamController.broadcast();
    _controller.sink.add("增加数据");
    // _controller.stream.listen((event) {
    //   print(event);
    // }, onError: (err) => print("${err}"));
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: DefaultTextStyle(
          //设置字体
          style: Theme.of(context).textTheme.headline4,
          child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
            RaisedButton(
                child: Text("增加数据"),
                onPressed: () {
                  _controller.add('{"name":"wangsheng","age":19}');
                }),
            RaisedButton(
                child: Text("增加错误数据"),
                onPressed: () {
                  _controller.addError("state:500");
                }),
            RaisedButton(
                child: Text("关闭流"),
                onPressed: () {
                  _controller.sink.close();
                }),
            RaisedButton(
                child: Text("增加数字"),
                onPressed: () {
                  _controller.add(1111);
                }),
            StreamBuilder(
              stream: _controller.stream.map((event) => event * 3),
              builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
                switch (snapshot.connectionState) {
                  case ConnectionState.none:
                    return Text("NONE: 没有数据");
                    break;
                  case ConnectionState.waiting:
                    return Text("WAITING: 等待: ${snapshot.data}");
                    break;
                  case ConnectionState.active:
                    if (snapshot.hasError) {
                      return Text("ERROR: 错误: ${snapshot.error}");
                    }
                    return Text("Active: 正常: ${snapshot.data}");
                    break;
                  case ConnectionState.done:
                    return Text("DONE: 数据流已经关闭");
                    break;
                }
                return Container();
              },
            ),
          ]),
        ),
      ),
    );
  }
}


四.fultter程序中key

其实一直以来我对flutter中key一直不是很了解,因为flutter在帮我自动生成的时候,不是多此一举吗。其实不然。要理解key的使用,首先得明白fultter的weight Tree和element Tree。这两者之间得关系,就好java中class和实例得关系。class里面得一些方法和属性是来描述一个东西,weight Tree也是一样,可以理解为蓝图。weight Tree找到element Tree,你按照我描绘的渲染页面,这俩者是一个对应得关系。element Tree负责管理状态State。那么这两者之间是一个对应的关系,flutter是通过从weight Tree找到element Tree的呢?如果找不到又会发生什么。第一个是找类型,第二个是找key。在flutter中我们会很少使用到key,一般是通过类型。运行下面一段程序,交换Box的位置,分别加key和不加key的区别

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

class KeyDemo extends StatefulWidget {
  @override
  _KeyDemoState createState() => _KeyDemoState();
}

class _KeyDemoState extends State<KeyDemo> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Box(Colors.blue,key: ValueKey(4)),
            Box(Colors.deepPurple,key: ValueKey(3)),
            Box(Colors.deepPurple,key: ValueKey(1)),
          ],
        ),
      ),
    );
  }
}

class Box extends StatefulWidget {
  final Color color;

  Box(this.color, {Key key}):super(key:key);

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

class _BoxState extends State<Box> {
  int _count = 0;

  @override
  Widget build(BuildContext context) {
    return InkWell(
        child: Container(
          width: 150,
          height: 80,
          color: widget.color,
          child: Center(
            child: Text(_count.toString(), style: TextStyle(fontSize: 60)),
          ),
        ),
        onTap: () {
          setState(() {
            _count++;
          });
        });
  }
}



总结

其实概念这东西也很重要,虽说我们学程序是以实际开发为主,他能帮助我们快速与已有的思维模型建立联系
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值