如今公司用flutter开发项目,写了几个月的业务,对于widget的生命周期也朦朦胧胧,如今得空来探知下。
测试界面
图片.png
最外层一个Scaffold
包着父widget
,是个StatefulBuilder
,点击按钮父组件刷新,就会刷新StatefulBuilder
,
子widget
是个LifecycleStateful
,打印state
生命周期的方法
class LifecycleDemoPage extends StatelessWidget {
const LifecycleDemoPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
...
body: StatefulBuilder(builder: (context,setter){
return Column(
children: [
ElevatedButton(onPressed: (){
setter.call((){});
}, child: Text('父组件刷新')),
LifecycleStateful(),
],
);
}));
}
}
class LifecycleStateful extends StatefulWidget {
@override
State<StatefulWidget> createState(){
LogUtils.d("createState ${toStringShort()}#$hashCode");
return LifecycleStatefulState();
}
}
class LifecycleStatefulState extends State<LifecycleStateful> {
int click = 0;
@override
void initState() {
super.initState();
LogUtils.d("State initState ${toStringShort()}");
}
@override
void dispose() {
// TODO: implement dispose
super.dispose();
LogUtils.d("State dispose ${toStringShort()}");
}
@override
void deactivate() {
// TODO: implement deactivate
super.deactivate();
LogUtils.d("State deactivate ${toStringShort()}");
}
@override
void activate() {
// TODO: implement activate
super.activate();
LogUtils.d("State activate ${toStringShort()}");
}
@override
void reassemble() {
// TODO: implement reassemble
super.reassemble();
LogUtils.d("State activate ${toStringShort()}");
}
@override
void didChangeDependencies() {
// TODO: implement didChangeDependencies
super.didChangeDependencies();
LogUtils.d("State didChangeDependencies ${toStringShort()}");
}
@override
void didUpdateWidget(covariant LifecycleStateful oldWidget) {
// TODO: implement didUpdateWidget
super.didUpdateWidget(oldWidget);
LogUtils.d("State didUpdateWidget ${toStringShort()}");
}
List<Widget> children =[];
bool newChild = false;
@override
Widget build(BuildContext context) {
LogUtils.d("State build ${toStringShort()}");
if(children.isEmpty){
children = [
ElevatedButton(
onPressed: () {
setState(() {
click++;
});
},
child: Text("click $click")),
ElevatedButton(
onPressed: () {
setState(() {
children.add(Text("i am add"));
});
},
child: Text("添加子child")),
ElevatedButton(
onPressed: () {
setState(() {
newChild=!newChild;
});
},
child: Text("change")),
];
}
return newChild?ElevatedButton(onPressed: (){
setState(() {
newChild=!newChild;
});
}, child: Text('change')):Container(
padding: EdgeInsets.all(16),
child: Column(
children:children ,
),
);
}
}
进入界面时LifecycleStateful
生命周期方法调用输出
I/flutter ( 7336): LifecycleStateful.createState (package:flutter_demo/demo/life_cycler/life_cycler_demo_page.dart:38:14)
I/flutter ( 7336):LifecycleStatefulState.initState (package:flutter_demo/demo/life_cycler/life_cycler_demo_page.dart:48:14)
I/flutter ( 7336): LifecycleStatefulState.didChangeDependencies (package:flutter_demo/demo/life_cycler/life_cycler_demo_page.dart:78:14)
I/flutter ( 7336): LifecycleStatefulState.build (package:flutter_demo/demo/life_cycler/life_cycler_demo_page.dart:89:14)
结论:生命周期调用依次
createState ,State构造器,initState,didChangeDependencies,build
方法
点击父组件刷新按钮,此时父控件刷新,作为子控件的LifecycleStateful
生命周期方法调用输出
I/flutter (22291): LifecycleStatefulState.didUpdateWidget (package:flutter_demo/demo/life_cycler/life_cycler_demo_page.dart:102:14)
I/flutter (22291): LifecycleStatefulState.build (package:flutter_demo/demo/life_cycler/life_cycler_demo_page.dart:108:14)
父控件刷新,子控件
LifecycleStateful
会调用didUpdateWidget ,build
点击click
,调用setState
方法,只调用了build
方法
I/flutter ( 7336):LifecycleStatefulState.build (package:flutter_demo/demo/life_cycler/life_cycler_demo_page.dart:89:14)
切换主题颜色后调用了didUpdateWidget
和build
方法
I/flutter (22291): LifecycleStatefulState.didUpdateWidget (package:flutter_demo/demo/life_cycler/life_cycler_demo_page.dart:92:14)
I/flutter (22291): LifecycleStatefulState.build (package:flutter_demo/demo/life_cycler/life_cycler_demo_page.dart:98:14)
返回退出,依次调用deactivate
和dispose
方法
I/flutter (22291): LifecycleStatefulState.deactivate (package:flutter_demo/demo/life_cycler/life_cycler_demo_page.dart:78:14)
I/flutter (22291): LifecycleStatefulState.dispose (package:flutter_demo/demo/life_cycler/life_cycler_demo_page.dart:72:14)
可以看到从进入到退出initState
只打印一次。类似View
的onAttachedToWindow
方法,build
方法
就类似draw
方法每次刷新会调用。dispose
方法类似onDetachedFromWindow
。只不过View
的生命周期方法还有其他,颗粒度更细些。
结论:生命周期开始调用
initState
,更新会多次调用build
和didUpdateWidget
,销毁调用dispose
didChangeDependencies
方法除进入界面调用,就没在调用过。看源码注释说是和InheritedWidget
有关
/// Called when a dependency of this [State] object changes.
///
/// For example, if the previous call to [build] referenced an
/// [InheritedWidget] that later changed, the framework would call this
/// method to notify this object about the change.
///
为此另写代码继承InheritedWidget
控件,
界面如下:就一个InheritedWidget
包裹着一个Text
,和一个按钮,
按钮点击一下,count+=1
并刷新,
示例代码
class ShareDataWidget extends InheritedWidget {
final int data; //需要在子树中共享的数据,保存点击次数
ShareDataWidget({
Key? key,
required this.data,
required Widget child,
}) : super(key: key, child: child);
//定义一个便捷方法,方便子树中的widget获取共享数据
static ShareDataWidget? of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<ShareDataWidget>();
}
//定义一个便捷方法,方便子树中的widget获取共享数据
static ShareDataWidget? of2(BuildContext context) {
//return context.dependOnInheritedWidgetOfExactType<ShareDataWidget>();
return (context.getElementForInheritedWidgetOfExactType<ShareDataWidget>()!.widget as ShareDataWidget );
}
//该回调决定当data发生变化时,是否通知子树中依赖data的Widget
@override
bool updateShouldNotify(covariant ShareDataWidget oldWidget) {
// TODO: implement updateShouldNotify
return false;
}
}
class _TestWidget extends StatefulWidget {
@override
__TestWidgetState createState() => __TestWidgetState();
}
class __TestWidgetState extends State<_TestWidget> {
@override
Widget build(BuildContext context) {
//使用InheritedWidget中的共享数据
return Text(ShareDataWidget.of(context)!.data.toString());
// return Text("aaa");
}
@override
void didUpdateWidget(covariant _TestWidget oldWidget) {
// TODO: implement didUpdateWidget
super.didUpdateWidget(oldWidget);
print("didUpdateWidget");
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
//父或祖先widget中的InheritedWidget改变(updateShouldNotify返回true)时会被调用。
//如果build中没有依赖InheritedWidget,则此回调不会被调用。
print("Dependencies change");
}
}
class InheritedWidgetTestRoute extends BasePage {
InheritedWidgetTestRoute({ super.title:"InheritedWidget数据共享"});
int count = 0;
@override
Widget body(BuildContext context) {
return Center(
child: ShareDataWidget( //使用ShareDataWidget
data: count,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(bottom: 20.0),
child: _TestWidget(),//子widget中依赖ShareDataWidget
),
ElevatedButton(
child: Text("Increment"),
//每点击一次,将count自增,然后重新build,ShareDataWidget的data将被更新
onPressed: () => setState(() => ++count),
)
],
),
),
);
}
}
注意上面updateShouldNotify
方法返回false
,点击按钮后,子widget
调用
I/flutter (22291): didUpdateWidget
I/flutter (22291): build
修改updateShouldNotify
返回true
I/flutter (22291): didUpdateWidget
I/flutter (22291): Dependencies change
I/flutter (22291): build
结论:当
InheritedWidget
中updateShouldNotify
返回false时,子widget
也只调用didUpdateWidget
和build
,
当updateShouldNotify
返回true时,子widget
依次调用didUpdateWidget
,didChangeDependencies
,build
网友评论