Flutter 局部Widget刷新
Posted 123_000000
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flutter 局部Widget刷新相关的知识,希望对你有一定的参考价值。
更新局部Widget,避免全局刷新 ,总结自己遇到和需要的情况整理如下,原理不做解释,只记录用法
1、GlobalKey
通过传递GlobalKey 获取Widget的State, 调用 setState(VoidCallback fn) 刷新Widget
注意:使用GlobalKey开销较大,如果有其他可选方案,应尽量避免使用它。另外同一个GlobalKey在整个widget树中必须是唯一的,不能重复 。
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '动态更新叶子节点的Widget',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: '动态更新叶子节点的Widget'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
//设置key,绑定待刷新控件.
GlobalKey textKey = GlobalKey();
@override
Widget build(BuildContext context) {
print('Enter _MyHomePageState.build()');
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
TextWidget(textKey),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
_counter++;
//动态刷新局部widget(widget内部更新)
(textKey.currentState as TextWidgetState).onPressed(_counter);
},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
//********使用GlobalKey局部刷新*****/
class TextWidget extends StatefulWidget {
//! 接收传过来的key
TextWidget(Key key) : super(key: key);
@override
State createState() {
return TextWidgetState();
}
}
class TextWidgetState extends State<TextWidget> {
int _counter = 0;
@override
Widget build(BuildContext context) {
return Center(
child: Text(
'$_counter',
style: TextStyle(fontSize: 20, color: Colors.green),
),
);
}
//在TextWidget的onPressed中单独调用TextWidget的setState,刷新本控件.
void onPressed(int count) {
setState(() {
_counter = count;
});
}
}
2、替换Wiget,Element update(covariant Widget newWidget)
感觉类似于android 的切换缓存的Fragment 列表来更新布局。
以下demo,创建两个TextUpdateWidget存于upWidgetPages中,counter奇偶判断切换两个TextUpdateWidget的显示。
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: '动态替换叶子节点的Widget',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: '动态替换叶子节点的Widget'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
//用于更换的组件,类似于Android fragment替换更新
TextUpdateWidget updateWidget;
//存储组件列表
List<Widget> upWidgetPages = [];
static Element findChild(Element e, Widget w) {
Element child;
void visit(Element element) {
if (w == element.widget)
child = element;
else
element.visitChildren(visit);
}
visit(e);
return child;
}
@override
Widget build(BuildContext context) {
print('Enter _MyHomePageState.build()');
updateWidget = TextUpdateWidget(counter: _counter);
upWidgetPages.add(updateWidget);
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
updateWidget,
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
print('Enter floatingActionButton.onPressed()');
_counter++;
//创建widget 存于upWidgetPages 用于替换
if (_counter == 1) {
TextUpdateWidget updateWidget = TextUpdateWidget(counter: _counter);
upWidgetPages.add(updateWidget);
}
Element e = findChild(context as Element, updateWidget);
if (e != null) {
if ((_counter + 1) % 2 == 1) {
updateWidget = upWidgetPages[0];
} else {
updateWidget = upWidgetPages[1];
}
e.owner.lockState(() {
e.update(updateWidget);
});
}
},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
//*******局部替换Widget********/
class TextUpdateWidget extends StatefulWidget {
int counter = 0;
TextUpdateWidget({Key key, this.counter}) : super(key: key);
@override
State<StatefulWidget> createState() => TextUpdateWidgetState();
}
class TextUpdateWidgetState extends State<TextUpdateWidget> {
@override
Widget build(BuildContext context) {
return Center(
child: (widget.counter + 1) % 2 == 0
? Text('another times: ${widget.counter}',
style: TextStyle(fontSize: 24, color: Colors.cyan))
: Text('another times: ${widget.counter}',
style: TextStyle(fontSize: 28, color: Colors.amberAccent)),
);
}
}
3、Provider 状态共享,更新wiget
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// return MultiProvider(
// providers: [
// //这里是关键注册通知吧
// ChangeNotifierProvider(create: (_) => Counter()),
// ],
// child: MaterialApp(
// title: 'Test',
// //设置主题
// theme: ThemeData(primaryColor: Colors.pink),
// home: CountPage(),
// ),
// );
return ChangeNotifierProvider(
create: (_) => Counter(),
child: MaterialApp(
title: 'Test',
theme: ThemeData(primaryColor: Colors.pink),
home: CountPage(),
),
);
}
}
class CountPage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return CountPageState();
}
}
class CountPageState extends State<CountPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("你都点击${Provider.of<Counter>(context).value}次了",
style: TextStyle(
color: Colors.red,
fontSize: 33.0,
)),
TextUpdateWidget()
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Provider.of<Counter>(context, listen: false)..increment();
},
tooltip: 'add',
child: Icon(Icons.add),
));
}
}
class TextUpdateWidget extends StatefulWidget {
@override
State<StatefulWidget> createState() => TextUpdateWidgetState();
}
class TextUpdateWidgetState extends State<TextUpdateWidget> {
@override
Widget build(BuildContext context) {
return Center(
child: (Provider.of<Counter>(context).value + 1) % 2 == 0
? Text('another times: ${Provider.of<Counter>(context).value}',
style: TextStyle(fontSize: 24, color: Colors.cyan))
: Text('another times: ${Provider.of<Counter>(context).value}',
style: TextStyle(fontSize: 28, color: Colors.amberAccent)),
);
}
}
//混入
class Counter with ChangeNotifier {
int value = 0;
increment() {
value += 1;
//发送通知
notifyListeners();
}
}
以上是关于Flutter 局部Widget刷新的主要内容,如果未能解决你的问题,请参考以下文章