第一种 :使用 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
extends StatefulWidget> - @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<PartRefreshWidget> {
-
- 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<GlobalKeyDemo> {
- 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<MyHomePage> {
-
- Future<String> 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<MyHomePage> {
-
- Stream<int> 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<int> 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