第一种 :使用 GlobalKey
父组件中声明
GlobalKey<_局部刷新对象类型State> textKey = GlobalKey();
textKey.currentState.局部刷新的方法();
第二种
使用:StatefulBuilder
第三种
使用 StreamBuilder + StreamController FutureBuilder & StreamBuilder
第三种:provider (也是异步通信)
ChangeNotifier + ChangeNotifierProvider
第四种 (也是异步通信) :Flutter ValueNotifier 异步通信、ValueListenableBuilder - 知乎
ValueNotifier + ValueListenableBuilder
globalkey唯一定义了某个element,它使你能够访问与element相关联的其他对象,例如buildContext、state等。
使用场景:可以通过key.currentState拿到它的状态对象,然后就可以调用其中的onPressed方法。
//请求刷新
setState((){
});
#State
@override
Widget build(BuildContext context) {
//构建新的Widget
return new Text(_text);
}
那么,如果 我们能将 build方法中的 return new Text(_text) 暴漏出去,我们就可以实现通用的 局部刷新 Widget。
用typedef function实现
//定义函数别名
typedef BuildWidget = Widget Function();
将函数别名 BuildWidget 作为参数,传递到State.build方法即可
完整代码
import 'package:flutter/material.dart';
//封装 通用局部刷新工具类
//定义函数别名
typedef BuildWidget = Widget Function();
class PartRefreshWidget extends StatefulWidget {
PartRefreshWidget(Key key, this._child): super(key: key);
BuildWidget _child;
@override
State createState() {
return PartRefreshWidgetState(_child);
}
}
class PartRefreshWidgetState extends State {
BuildWidget child;
PartRefreshWidgetState(this.child);
@override
Widget build(BuildContext context) {
return child.call();
}
void update() {
print('update');
setState(() {
});
}
}
使用:
import 'package:flutter/material.dart';
import 'PartRefreshWidget.dart';
class GlobalKeyDemo extends StatefulWidget {
@override
_GlobalKeyDemoState createState() => _GlobalKeyDemoState();
}
class _GlobalKeyDemoState extends State {
int _count = 0;
//使用1 创建GlobalKey
GlobalKey globalKey = new GlobalKey();
@override
Widget build(BuildContext context) {
print('----------------build');
return Scaffold(
appBar: AppBar(
title: Text("inheritedWidget"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
//使用2 创建通用局部刷新widget
PartRefreshWidget(globalKey, () {
///创建需要局部刷新的widget
return Text(
'变化的:$_count',
style: TextStyle(color: Colors.green),
);
}),
Text('不变的: $_count'),
RaisedButton(
onPressed: () {
//点击
_count++;
//使用3调用刷新方法
globalKey.currentState.update();
},
),
],
),
)
);
}
}
转载:https://blog.csdn.net/jdsjlzx/article/details/123560075
使用情景:
多选和单选
单选的时候,选中一个就可以直接把结果返回,因此本身底部弹窗无需状态管理。但到多选的时候,需要知道当前选中的选项,有选项被点击的时候需要存储下来,当再次被点击的时候要清空这个选项,同时界面还需要同步更新,因此就涉及到状态管理了。
实现方式 内部使用。
在Flutter 中提供了一个 StatefulBuilder
的类,提供了一个 builder
方法构建有状态组件,并且提供了状态更新方法,因此在里面完成状态管理。
在这个 builder
方法中,setState
其实就是对应状态组件的setState
对应的方法,这个 state 就是用于控制 StatefulBuilder
生成的组件的状态的。这种方式有点类似于 React
的 useState
的钩子函数用法
使用的核心代码:
class DemoStatefulBuilderPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
//状态构建器
body: buildStatefulBuilder(),
);
}
}
int _count = 0;
StatefulBuilder buildStatefulBuilder() {
return StatefulBuilder(
//构建状态改变的Widget
builder: (BuildContext context, void Function(void Function()) setState) {
//居中
return Center(
//手势识别
child: GestureDetector(
child: Text("早起的年轻人 $_count"),
//单击事件
onTap: () {
//刷新当前 StatefulBuilder 中的状态
setState(() {
_count++;
});
},
),
);
},
);
}
使用场景:异步UI更新
很多时候我们会依赖一些异步数据来动态更新UI,比如在打开一个页面时我们需要先从互联网上获取数据,在获取数据的过程中显示一个加载框,等获取到数据时我们再渲染页面;又比如我们想展示Stream(比如文件流、互联网数据接收流)的进度。当然StatefulWidget我们完全可以实现以上功能。但由于在实际开发中依赖异步数据更新UI的这种场景非常常见,并且当StatefulWidget中控件树较大时,更新一个属性导致整个树重建,消耗性能,因此Flutter专门提供了FutureBuilder和SteamBuilder两个组件来快速实现这种功能。
const FutureBuilder({
Key key,
this.future, //获取数据的方法 获取用户异步处理获得数据的代码
this.initialData, //初始的默认数据 初始化数据加载
@required this.builder //数据快照 回调函数,暴露异步处理中的快照。这个是我们构建组件的主要组成。 主要来看一下它的构造函数:
}) : assert(builder != null),
super(key: key);
class _MyHomePageState extends State {
Future mockNetworkData() async {
return Future.delayed(Duration(seconds: 2), () => "我是从互联网上获取的数据");
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'You have pushed the button this many times:',
),
FutureBuilder(
future: mockNetworkData(),
builder: (BuildContext context, AsyncSnapshot snapshot){
if(snapshot.connectionState == ConnectionState.done){
if(snapshot.hasError){
// 请求失败,显示错误
return Text("Error: ${snapshot.error}");
}else {
// 请求成功,显示数据
return Text("Contents: ${snapshot.data}");
}
}else {
return CircularProgressIndicator();
}
}),
],
),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
class _MyHomePageState extends State {
Stream counter(){
return Stream.periodic(Duration(seconds: 1), (i){
return i;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'You have pushed the button this many times:',
),
StreamBuilder(
stream: counter(),
builder: (BuildContext context, AsyncSnapshot snapshot){
if(snapshot.hasError){
return Text("Error: ${snapshot.error}");
}
switch (snapshot.connectionState){
case ConnectionState.none:
return Text("没有Stream");
case ConnectionState.waiting:
return Text("等待数据、、、");
case ConnectionState.active:
return Text("active: ${snapshot.data}");
case ConnectionState.done:
return Text("Stream已关闭");
}
return null;
}),
],
),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
StreamBuilder与StreamController的详细使用:https://blog.csdn.net/u010194271/article/details/128024208