Skip to content

Commit 21927e3

Browse files
author
zengsong
committed
upload new files
1 parent becb40c commit 21927e3

12 files changed

+1059
-0
lines changed
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
### AsyncBuilder介绍
2+
AsyncBuilder名字起得有点怪,实际上它是一个Widget控件[[官方文档]]([https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html](https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html)
3+
),它把异步操作与数据更新结合在一起,举个例子,以首页为例,通常显示首页的时候会先判断首页数据拉取下来了没,没有没有就显示loading,如果有就直接渲染首页数据,代码逻辑大概是这样
4+
```java
5+
if (data == null) {
6+
fetchData();
7+
showLoading();
8+
} else {
9+
showMainPage();
10+
hideLoading();
11+
}
12+
```
13+
可以看出来数据的获取跟ui的更新都是分开的,而AsyncBuilder正是把数据获取与数据ui更新绑定在一起,在使用AsyncBuilder时我们只需要给它传递一个Future对象,负责数据的获取,以及实现一个AsyncWidgetBuilder回调方法,负责对应ui的创建显示即可,下面具体说说它的用法。
14+
15+
### AsyncBuilder使用介绍
16+
- 构造方法
17+
```java
18+
FutureBuilder({Key key, Future<T> future, T initialData, @required AsyncWidgetBuilder<T> builder })
19+
```
20+
`future` : 异步io操作的Future对象
21+
`initialData` : 默认初始化数据
22+
`builder` : 负责根据不同状态创建对应ui的方法实现
23+
- Future对象
24+
future对象的创建必须要提前,譬如可以在 State.initState State.didUpdateConfig, 或者 State.didChangeDependencies等时期创建,不能在State.build 或者StatelessWidget.build回调时去创建,如果在创建FutureBuilder时同时创建Future,那么一旦FutureBuilder的parent Widget发生变化时,异步任务都会被触发。
25+
26+
- AsyncWidgetBuilder 方法
27+
AsyncWidgetBuilder是接受两个参数`BuildContext context``AsyncSnapshot<T> snapshot`并且返回一个Widget对象的方法,其中`AsyncSnapshot<T> snapshot`包含了异步io操作的一些信息回调,其中有:
28+
1 `connectionState `:枚举对象,它的值可以是`none` `waiting ` `active ` `done `
29+
2 `data `:异步io处理完时回调的数据
30+
3 `error `:异步io处理发生错误时回调
31+
32+
### 完整例子
33+
下面给出一个完整的代码例子,启动页面的时候会先显示Awaiting的状态,同时会去请求百度的页面,请求回来了就打印下数据
34+
```java
35+
import 'package:flutter/material.dart';
36+
import 'dart:io';
37+
import 'dart:convert';
38+
/**
39+
* Created by nls on 2019/7/20.
40+
* Nothing.
41+
*/
42+
class FutureBuilderDemo extends StatelessWidget {
43+
@override
44+
Widget build(BuildContext context) {
45+
return MaterialApp(
46+
theme: ThemeData(primaryColor: Colors.blue),
47+
home: HomeWidget());
48+
}
49+
}
50+
51+
class HomeWidget extends StatefulWidget {
52+
@override
53+
State createState() {
54+
return HomeState();
55+
}
56+
}
57+
58+
class HomeState extends State<HomeWidget> {
59+
var futureFetchData;
60+
@override
61+
void initState() {
62+
super.initState();
63+
futureFetchData = fetchData();
64+
}
65+
66+
Future<String> fetchData() async {
67+
var httpClient = new HttpClient();
68+
var uri = Uri.parse('http://www.baidu.com');
69+
var request = await httpClient.getUrl(uri);
70+
var response = await request.close();
71+
var responseBody = await response.transform(utf8.decoder).join();
72+
return responseBody;
73+
}
74+
75+
@override
76+
Widget build(BuildContext context) {
77+
return Scaffold(
78+
appBar: AppBar(title: Text("futureBuilder")),
79+
body: Container(
80+
padding: const EdgeInsets.all(10),
81+
child: FutureBuilder<String>(
82+
future: futureFetchData, // a previously-obtained Future<String> or null
83+
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
84+
switch (snapshot.connectionState) {
85+
case ConnectionState.none:
86+
return Text('Press button to start.');
87+
case ConnectionState.active:
88+
case ConnectionState.waiting:
89+
return Text('Awaiting result...');
90+
case ConnectionState.done:
91+
if (snapshot.hasError)
92+
return Text('Error: ${snapshot.error}');
93+
return Text('Result: ${snapshot.data}');
94+
}
95+
return null; // unreachable
96+
},
97+
),
98+
)
99+
);
100+
}
101+
}
102+
103+
```
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
### StreamBuilder介绍
2+
前面介绍过FutureBuilder,它是一个Widget控件,提供了异步数据获取与ui更新的能力,StreamBuilder与FutureBuilder类似[[官方文档]]([https://api.flutter.dev/flutter/widgets/StreamBuilder-class.html](https://api.flutter.dev/flutter/widgets/StreamBuilder-class.html)
3+
),也是一个Widget控件,不一样的是FutureBuilder依靠Future来做异步数据获取,而StreamBuilder则是依赖Stream来做异步数据获取。
4+
5+
### Stream介绍
6+
在讲StreamBuilder前得先介绍下Stream这个东西。通俗点讲,Stream就是个事件流,有点类似于RxJava,它允许我们从一端发射一个事件,从另外一端去监听事件的变化,通过Stream我们可以在Flutter上设计出基于事件流驱动的响应式代码逻辑。
7+
8+
### Stream的简单实用
9+
事实上Stream并是不Flutter的产物,而是由Dart提供的,Stream是一个抽象的接口,Dart提供了StreamController接口类可以让我们方便的使用Stream,步骤大致如下:
10+
- 创建`StreamController`
11+
- 获取`StreamSink `用作发射事件
12+
- 获取`Stream`用作事件的监听
13+
- 获取`StreamSubscription `用作管理监听,关闭暂停等
14+
```dart
15+
StreamSubscription<String> subscription;
16+
//创建StreamController
17+
var streamController = StreamController<String>();
18+
// 获取StreamSink用于发射事件
19+
StreamSink<String> get streamSink => streamController.sink;
20+
// 获取Stream用于监听
21+
Stream<String> get streamData => streamController.stream;
22+
23+
//监听事件
24+
subscription = streamData.listen((value) {
25+
// do something
26+
});
27+
28+
//发射一个事件.
29+
streamSink.add(index.toString());
30+
```
31+
32+
### StreamBuilder的使用介绍
33+
- 构造方法
34+
```dart
35+
StreamBuilder({Key key, T initialData, Stream<T> stream, @required AsyncWidgetBuilder<T> builder })
36+
```
37+
`initialData` : 默认初始化数据
38+
`stream` : stream事件流对象
39+
`builder` : 负责根据不同状态创建对应ui的方法实现
40+
AsyncWidgetBuilder前面在讲FutureBuilder的时候已经介绍过,这里不再赘述。
41+
- 其他方法
42+
`afterConnected`:返回一个AsyncSnapshot,当订阅了stream时会回调此AsyncSnapshot
43+
`afterData`:返回一个AsyncSnapshot,当stream有事件触发时会回调此AsyncSnapshot
44+
`afterDisconnected`:返回一个AsyncSnapshot,当取消订阅stream时会回调此AsyncSnapshot
45+
`afterDone`:返回一个AsyncSnapshot,当stream被关闭时会回调此AsyncSnapshot
46+
`afterError`:返回一个AsyncSnapshot,stream发生错误时会回调此AsyncSnapshot
47+
48+
StreamBuilder 内部已经帮我们完成了stream的订阅与取消订阅,在initState的时候进行事件的订阅,在dispose的时候进行事件的反订阅,源码在`_StreamBuilderBaseState`里,关键过程大致如下
49+
```dart
50+
void initState() {
51+
super.initState();
52+
_summary = widget.initial();
53+
_subscribe();
54+
}
55+
56+
void dispose() {
57+
_unsubscribe();
58+
super.dispose();
59+
}
60+
void _subscribe() {
61+
if (widget.stream != null) {
62+
_subscription = widget.stream.listen((T data) {
63+
setState(() {
64+
_summary = widget.afterData(_summary, data);
65+
});
66+
}, onError: (Object error) {
67+
setState(() {
68+
_summary = widget.afterError(_summary, error);
69+
});
70+
}, onDone: () {
71+
setState(() {
72+
_summary = widget.afterDone(_summary);
73+
});
74+
});
75+
_summary = widget.afterConnected(_summary);
76+
}
77+
}
78+
void _unsubscribe() {
79+
if (_subscription != null) {
80+
_subscription.cancel();
81+
_subscription = null;
82+
}
83+
}
84+
```
85+
从上面的源码里面我们也可以清楚得看见StreamBuilder的各个回调方法的调用过程。
86+
87+
### 完整例子
88+
下面给出一个完整的代码例子,我们的页面在初始化的时候创建了`StreamController`,页面上面有个按钮,当点击按钮的时候就会发射出一个事件,StreamBuilder订阅了这个事件,并且把data打印出来
89+
```dart
90+
import 'dart:async';
91+
92+
import 'package:flutter/material.dart';
93+
import 'dart:io';
94+
import 'dart:convert';
95+
96+
/**
97+
* Created by nls on 2019/7/20.
98+
* Nothing.
99+
*/
100+
class StreamBuilderDemo extends StatelessWidget {
101+
@override
102+
Widget build(BuildContext context) {
103+
return MaterialApp(
104+
theme: ThemeData(primaryColor: Colors.blue),
105+
home: HomeWidget());
106+
}
107+
}
108+
109+
class HomeWidget extends StatefulWidget {
110+
@override
111+
State createState() {
112+
return HomeState();
113+
}
114+
}
115+
116+
class HomeState extends State<HomeWidget> {
117+
var index = 0;
118+
StreamSubscription<String> subscription;
119+
//创建StreamController
120+
var streamController;
121+
// 获取StreamSink用于发射事件
122+
StreamSink<String> get streamSink => streamController.sink;
123+
// 获取Stream用于监听
124+
Stream<String> get streamData => streamController.stream;
125+
126+
void onFloatActionButtonPress() {
127+
//发射一个事件.
128+
streamSink.add(index.toString());
129+
index++;
130+
}
131+
132+
@override
133+
void initState() {
134+
super.initState();
135+
streamController = StreamController<String>();
136+
streamSink.add("0");
137+
}
138+
139+
@override
140+
Widget build(BuildContext context) {
141+
return Scaffold(
142+
appBar: AppBar(title: Text('streamBuilder')),
143+
body: Center(
144+
child: Column(
145+
mainAxisAlignment: MainAxisAlignment.center,
146+
children: <Widget>[
147+
StreamBuilder<String>(
148+
stream: streamData,
149+
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
150+
return Text('Result: ${snapshot.data}');
151+
}
152+
)
153+
],
154+
)
155+
),
156+
floatingActionButton: FloatingActionButton(
157+
onPressed: onFloatActionButtonPress,
158+
child: Icon(Icons.add))
159+
);
160+
}
161+
}
162+
```
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
### BackdropFilter 介绍
2+
BackdropFilter可以用于对背景图片进行高斯模糊设置或者矩阵变换,除了图片以外BackdropFilter还能对任何子widget进行高斯模糊设置。BackdropFilter的定义如下:
3+
```dart
4+
BackdropFilter({Key key,
5+
@required ImageFilter filter,
6+
Widget child })
7+
```
8+
核心参数是filter,它是个ImageFilter类型,ImageFilter有两种构造方法,分别是用来设置背景高斯模糊以及矩阵变换的:
9+
10+
- 设置高斯模糊
11+
```dart
12+
//构造一个设置高斯模糊的ImageFilter,sigmaX,sigmaY用来控制
13+
//模糊度,取值范围是0-10
14+
ImageFilter.blur({double sigmaX: 0.0, double sigmaY: 0.0 })
15+
```
16+
17+
- 设置矩阵变换
18+
```dart
19+
ImageFilter.matrix(
20+
Float64List matrix4,
21+
{ FilterQuality filterQuality: FilterQuality.low })
22+
```
23+
**需要注意的是BackdropFilter不是变换背景来实现高斯模糊的效果,而是通过在背景上面盖上一个模糊层从而达到高斯模糊的效果,因此要做模糊的背景图必须要在BackdropFilter底下**
24+
25+
### BackdropFilter 使用
26+
可以通过`Stack `来控制布局的层次摆放,下面给一个例子来演示下BackdropFilter的使用
27+
```dart
28+
class HomeState extends State<HomeWidget> {
29+
30+
@override
31+
Widget build(BuildContext context) {
32+
return Scaffold(
33+
appBar: AppBar(title: Text("BackdropFilterDemo")),
34+
body: Stack(
35+
children: <Widget>[
36+
Container(
37+
alignment: Alignment.center,
38+
child: Image.network("http://img.redocn.com/sheying/20150213/mulanweichangcaoyuanfengjing_3951976.jpg",
39+
width: 300, height: 300,),
40+
),
41+
BackdropFilter(
42+
filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
43+
child: Container(
44+
color: Colors.white.withAlpha(0),
45+
),)
46+
],
47+
)
48+
);
49+
}
50+
}
51+
```
52+
效果如下
53+
![](https://upload-images.jianshu.io/upload_images/2829725-d3da7666fbf7932b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
54+
55+
BackdropFilter可以对一切背景设置高斯模糊效果,不仅限于图片,譬如我们把Image替换成Text,代码如下
56+
```dart
57+
class HomeState extends State<HomeWidget> {
58+
59+
@override
60+
Widget build(BuildContext context) {
61+
return Scaffold(
62+
appBar: AppBar(title: Text("BackdropFilterDemo")),
63+
body: Stack(
64+
children: <Widget>[
65+
Container(
66+
alignment: Alignment.center,
67+
child: Text("BackdropFilterDemo" * 10),
68+
),
69+
BackdropFilter(
70+
filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
71+
child: Container(
72+
color: Colors.white.withAlpha(0),
73+
),)
74+
],
75+
)
76+
);
77+
}
78+
}
79+
```
80+
效果如下
81+
![](https://upload-images.jianshu.io/upload_images/2829725-41e95aecb7ecf685.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
82+

0 commit comments

Comments
 (0)