当前位置:网站首页>Flutter tips: optimizing the buildcontext you use
Flutter tips: optimizing the buildcontext you use
2022-07-25 19:24:00 【Love cat de Xiaoguo】
Flutter Inside BuildContext I'm sure everyone will be familiar with , Although it's called Context, But it's actually Element The abstract object of , And in the Flutter in , It mainly comes from ComponentElement .
About ComponentElement Let me give you a brief introduction , stay Flutter According to the Element It can be simply summarized into two categories :
RenderObjectElement: HaveRenderObject, Have the ability of layout and drawing ElementComponentElement: No,RenderObject, That we use a lotStatelessWidgetandStatefulWidgetCorresponding toStatelessElementandStatefulElementIs its subclass .
So in general , We are build Methods or State What we got in BuildContext In fact, that is ComponentElement .
That use BuildContext Are there any problems that need attention ?
First, the following code is shown , In this example, when the user clicks FloatingActionButton When , There is one in the code 2 Second delay , Then call pop Exit the current page .
class _ControllerDemoPageState extends State<ControllerDemoPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
floatingActionButton: FloatingActionButton(
onPressed: () async {
await Future.delayed(Duration(seconds: 2));
Navigator.of(context).pop();
},
),
);
}
}
Under normal circumstances, there will be no problem , But when the user clicks FloatingActionButton after , Click again immediately AppBar Return to exit the application , At this time, the following error prompt will appear .

You can see at this time log say ,Widget Corresponding Element It's gone , Because in Navigator.of(context) When called ,context Corresponding Element It has been destroyed with our withdrawal .
In general, it is also very simple to deal with this problem , That is to increase mounted Judge , adopt mounted Judgment can avoid the above mistakes .
class _ControllerDemoPageState extends State<ControllerDemoPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
floatingActionButton: FloatingActionButton(
onPressed: () async {
await Future.delayed(Duration(seconds: 2));
if (!mounted) return;
Navigator.of(context).pop();
},
),
);
}
}
In the code above mounted The identification bit comes from State , because State Is attached to Element establish , So it can sense Element Life cycle of , for example mounted It is judgement. _element != null; .

So here we have gained a little skill : Use BuildContext when , When necessary, we need to pass mounted To ensure its effectiveness .
So just use mounted You can satisfy context Have you met the requirements of optimization ?
As shown in the following code , In this case :
- We added a list , Use
builderstructure Item - Each list has a click event
- When we click on the list, we simulate the network request , Suppose the network is not very good , So delay a 5 second
- Then we slide the list and click Item Slide out of the screen and not visible
class _ControllerDemoPageState extends State<ControllerDemoPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: ListView.builder(
itemBuilder: (context, index) {
return ListItem();
},
itemCount: 30,
),
);
}
}
class ListItem extends StatefulWidget {
const ListItem({Key? key}) : super(key: key);
@override
State<ListItem> createState() => _ListItemState();
}
class _ListItemState extends State<ListItem> {
@override
Widget build(BuildContext context) {
return ListTile(
title: Container(
height: 160,
color: Colors.amber,
),
onTap: () async {
await Future.delayed(Duration(seconds: 5));
if(!mounted) return;
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text("Tip")));
},
);
}
}
Because in 5 In seconds ,Item Was drawn out of the screen , So the corresponding Elment In fact, he was released , Thus, due to mounted Judge ,SnackBar Will not be ejected .
Suppose you need to show the results of click data reporting during development , That is to say Item It needs to pop up after being released , At this time, how to deal with ?
We know that whether it's ScaffoldMessenger.of(context) still Navigator.of(context) , Its essence is still through context Go up and find the corresponding InheritedWidget Generic , So we can get it in advance .
therefore , As shown in the following code , stay Future.delayed We passed before ScaffoldMessenger.of(context); Get sm object , After that, even if you exit the current list page directly ,5 Seconds later SnackBar Can also pop up normally .
class _ListItemState extends State<ListItem> {
@override
Widget build(BuildContext context) {
return ListTile(
title: Container(
height: 160,
color: Colors.amber,
),
onTap: () async {
var sm = ScaffoldMessenger.of(context);
await Future.delayed(Duration(seconds: 5));
sm.showSnackBar(SnackBar(content: Text("Tip")));
},
);
}
}
Why is the page destroyed , however SnackBar It can pop up normally ?
Because it passes of(context); Acquired ScaffoldMessenger Exist MaterialApp in , So even if the page is destroyed, it doesn't affect SnackBar Implementation .
But if we modify the example , As shown in the following code , stay Scaffold There is one more nested above ScaffoldMessenger , At this time Item Pass through ScaffoldMessenger.of(context) What you get will be under the current page ScaffoldMessenger .
class _ControllerDemoPageState extends State<ControllerDemoPage> {
@override
Widget build(BuildContext context) {
return ScaffoldMessenger(
child: Scaffold(
appBar: AppBar(),
body: ListView.builder(
itemBuilder: (context, index) {
return ListItem();
},
itemCount: 30,
),
),
);
}
}
In this case, we can only guarantee Item When it's invisible SnackBar It can pop up normally , And if we just exit the page at this time , The following error prompt will still appear , because ScaffoldMessenger Also destroyed .

So here we get the second trick : Use in asynchronous operations of(context) , It can be obtained in advance , Then do asynchronous operation , In this way, we can try our best to ensure the complete implementation of the process .
Since we are talking about passing of(context) Go to get the upper level share and the lower level share InheritedWidget , Where to get it is better ?
Remember the front log Do you ? When the first example goes wrong ,log There is a method in , That is to say State Of didChangeDependencies Method .

Why does the official suggest calling in this method of(context) ?
First of all, we have been saying , adopt of(context) What you get is InheritedWidget , and When InheritedWidget When there is a change , It is bound by triggering Element in State Of didChangeDependencies To trigger the update , So in didChangeDependencies Call inside of(context) There is a good causal relationship .
Interested in this part , You can see Flutter The trick is MediaQuery and build Optimize the secrets you don't know and Fully understand State And Provider .
Then I can initState Call in advance ?
Of course not , First, if in initState Call directly, such as ScaffoldMessenger.of(context).showSnackBar Method , You will see the following error prompt .

This is because Element I will judge this time _StateLifecycle state , If this is _StateLifecycle.created perhaps _StateLifecycle.defunct , That is to say initState and dispose , Is not allowed to execute of(context) operation .

of(context)Operation meanscontext.dependOnInheritedWidgetOfExactTyp.
Of course , If you just want to initState It's OK to adjust , Add one more Future The execution can be successful
@override
void initState() {
super.initState();
Future((){
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("initState")));
});
}
Simple understanding , because Dart It is a single thread polling execution ,
initStateInsideFutureEquivalent to the next poll , Of course not_StateLifecycle.createdUnder the state of .
Then I am build Can't you call directly in ?
Directly in build Calling in is sure to , although build Will be executed more frequently , however of(context) Operation is actually in a map Pass through key - value Get generic objects , So it won't have much impact on performance .
The real impact on performance is of(context) The number of bindings and the custom logic after getting the object , For example, you go through MediaQuery.of(context).size After getting the screen size , Locate your controls through a series of complex calculations .
@override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
var padding = MediaQuery.of(context).padding;
var width = size.width / 2;
var height = size.width / size.height * (30 - padding.bottom);
return Container(
color: Colors.amber,
width: width,
height: height,
);
}
For example, the above code , It may cause the keyboard to pop up , Although the current page is not fully displayed , But it will also cause your control to constantly recalculate, resulting in jamming .
Detailed explanation can refer to Flutter The trick is MediaQuery and build Optimize the secrets you don't know
So here we have another trick : about of(context) The related operation logic of , Try to put didChangeDependencies Go and deal with it .
Last , Today, I mainly shared using BuildContext Some precautions and skills in , If you have any questions about this , Feel free to leave a comment .
边栏推荐
- How to ensure the consistency of double write between database and cache?
- [hdlbits questions] Verilog language (3) modules: hierarchy section
- modelsim和quartus联合仿真PLL FIFO等IP核
- Istio exposes applications to the Internet
- SQL Server 2019 安装教程
- Solve the problem that the win10 account has no administrator rights
- 微信小程序 29 热搜榜的完善②
- Swift 基础 Codable(JSONEncoder JSONDecoder)的使用
- iMeta | Sangerbox: 交互式整合临床生信分析平台
- 哪吒 D1-H 测试 microbench
猜你喜欢

Small program completion work wechat campus maintenance application small program graduation design finished product (2) small program function
![[hdlbits questions] Verilog language (3) modules: hierarchy section](/img/35/ccdbb55aa0aff7e9dec2bf9e64c4e2.png)
[hdlbits questions] Verilog language (3) modules: hierarchy section

Swift 基础 Codable(JSONEncoder JSONDecoder)的使用

基于PHP的中非南南合作信息交流平台网站建设

The second "future Cup" knowledge map championship was officially launched

Pymoo learning (5): convergence analysis

The finished product of wechat campus maintenance and repair applet graduation design (1) development outline

Fruit chain "siege": it's a journey of sweetness and bitterness next to apples

歌曲转调之后和弦如何转换

高端旗舰投影仪选购指南:当贝X3 Pro、当贝F5观影更沉浸!
随机推荐
SQL Server 2019 安装教程
Why learn service grid istio
Grid layout frequently asked interview questions
Improvement of wechat applet 28 hot search list ①
[web technology] 1391 page visualization building tool, previous life and present life
伺服驱动器在机器人上的研究与应用
How to be a self disciplined person?
[encryption weekly] has the encryption market recovered? The cold winter has not thawed yet! Check the major events in the encryption market last week!
Hongmeng - Damiao computing Sketchpad - Introduction
The second "future Cup" knowledge map championship was officially launched
MES管理系统有什么应用价值
Imperial cms7.5 imitation "question and answer library" question and answer learning platform website source code with mobile version
Juzhi cloud computing opens a new era to the "proprietary cloud" of Youfu network
聊聊接口性能优化的11个小技巧
基于FPGA的1080P 60Hz BT1120接口调试过程记录
[applet development] detailed explanation of host environment
常用的开发软件下载地址
[919. Complete binary tree inserter]
QT compiled successfully, but the program could not run
某公司网络设计与规划