当前位置:网站首页>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 .
边栏推荐
- Selenium运行慢 - 通过设置selenium加载策略加快运行速度
- 高并发下如何保证数据库和缓存双写一致性?
- Intouch高级报警(报警筛选)
- 小程序毕设作品之微信校园维修报修小程序毕业设计成品(1)开发概要
- The degree of interval of basic music theory
- Fruit chain "siege": it's a journey of sweetness and bitterness next to apples
- CRM configuration item command notes
- FPGA based 1080p 60Hz bt1120 interface debugging process record
- Telnet installation and telnet (correct password) cannot log in!
- 乐理基础 调式
猜你喜欢

Swift 基础 Codable(JSONEncoder JSONDecoder)的使用
平衡二叉树

【刷题记录】21. 合并两个有序链表

聊聊接口性能优化的11个小技巧

Pymoo学习 (6):终止条件

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

小程序毕设作品之微信校园维修报修小程序毕业设计成品(5)任务书

【Web技术】1391- 页面可视化搭建工具前生今世

Use of swift basic codable (jsonencoder jsondecoder)

leetcode刷题:动态规划07(不同的二叉搜索树)
随机推荐
Pymoo学习 (7):并行化Parallelization
Clip can also do segmentation tasks? The University of Gottingen proposed a model clipseg that uses text and image prompt and can do three segmentation tasks at the same time, squeezing out the clip a
【HDLBits 刷题】Verilog Language(3)Modules: Hierarchy 部分
Wechat campus maintenance and repair applet graduation design finished product of applet completion work (4) opening report
Modelsim and quartus jointly simulate PLL FIFO and other IP cores
Pymoo learning (8):grades
CRM configuration item command notes
Why learn service grid istio
Youfu network was invited to attend the 2022 national CIO conference and won the title of "CIO trusted brand"
Fearless of high temperature and rainstorm, how can Youfu network protect you from worry?
李宏毅《机器学习》丨1. Introduction of this course(机器学习介绍)
Imperial cms7.5 imitation "question and answer library" question and answer learning platform website source code with mobile version
帝国CMS整站|手机号/QQ靓号商城源码|适配移动端
Huawei recruited "talented teenagers" twice this year; 5.4 million twitter account information was leaked, with a selling price of $30000; Google fired engineers who believed in AI consciousness | gee
TypeError: ‘str‘ object is not callable的错误原因
Basic music theory -- configuring chords
[encryption weekly] has the encryption market recovered? The cold winter has not thawed yet! Check the major events in the encryption market last week!
Pymoo学习 (5):收敛性分析
Basic mode of music theory
歌曲转调之后和弦如何转换