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++;
});
});
}
}