Delayed code execution in flutter

Sunbreak 2021-02-23 03:47:48
delayed code execution flutter


Original address :https://itnext.io/delayed-code-execution-in-flutter-23d60b51e76f

Original author :https://numen31337.medium.com/

Release time :2 month 7 Japan -8 Minutes reading

Microtask,Future still postFrameCallback, Which one should I use ?

In this article , I want to take you in Flutter Deep inside , Learn more about the little journey of scheduling code execution . As the beginning of a dialogue , Let's assume that we are using standard BLoC framework , Use Provider Library to build an application . To make the task challenging , After opening a new screen , We're going to have to make a network request , Get something through the Internet . under these circumstances , We have several options to initiate our request .

1. Get the data before we show our screen , Then display it with preloaded data , It may not be the best choice . It may not be the best choice . If you decide to get only part of the data you need , You are likely to load a lot of unnecessary data or block the user interface with a spinner .

  1. stay BLoC Start the loading process in , Just before the screen , When creating a BLoC Start it for you by itself or using the coordinator object . If you want to keep the architecture clean , This will be the recommended method .

  2. On the screen initState Start the loading process in , Try to encapsulate this logic in the screen itself .

The third solution may not be the best in terms of architectural correctness , But it's actually Flutter It's quite common in the world . Let's look at , Because it perfectly demonstrates our theme in real world scenes .

For demonstration purposes , Here is a sample code . Notice what's wrong with it ?

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(
MaterialApp(
title: 'Demo',
home: ChangeNotifierProvider(
create: (_) => MyHomePageBloc(),
child: MyHomePage(),
),
),
);
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
super.initState();
context.read<MyHomePageBloc>().fetchData();
}
@override
Widget build(BuildContext context) {
final bloc = context.watch<MyHomePageBloc>();
return Scaffold(
appBar: AppBar(),
body: Center(
child: bloc.loading ? CircularProgressIndicator() : Text(bloc.data),
),
floatingActionButton: FloatingActionButton(
onPressed: () => context.read<MyHomePageBloc>().fetchData(),
tooltip: 'Fetch',
child: Icon(Icons.add),
),
);
}
}
class MyHomePageBloc with ChangeNotifier {
String data = "Loading";
bool loading = false;
void fetchData() {
loading = true;
data = "Loading";
notifyListeners();
Future.delayed(Duration(seconds: 3), () {
loading = false;
data = "Done";
notifyListeners();
});
}
}
 Copy code 

At first glance , It seems that everything is normal . However , If you run it , It will inevitably collapse , You'll see something like that in your journal .‘package:flutter/src/widgets/framework.dart’: Failed assertion: line 4349 pos 12: ‘!_dirty’: is not true.

This error shows that , We are trying to modify it at build time widget Trees . Small component initState Methods are called in the middle of the build process , So any attempt to modify the widget tree from there will fail . In our case , When calling fetch When the method is used , It will execute synchronously notifyListeners(), Which leads to widget Trees change .

When you try to do more seemingly unrelated things , Similar errors may be encountered . for example , Show a conversation , It will fail for similar reasons , because Context ( Element) It is not currently mounted in the widget tree .

Whatever you want to do , You have to delay code execution , Until the build process is complete . let me put it another way , You need to execute your code asynchronously . Now let's talk about our choices .

How to be in Flutter Delay code execution in ?

By studying this topic on the Internet , I've compiled a list of the most common recommended solutions . You can even find some extra options , But here's the most compelling option .

You might say , That's a lot of options , You're right . Speaking of our above problems , Any one can be solved . however , Since we are faced with so many choices , Let's indulge our curiosity , Try to understand the difference between them .

Event loop and multithreading

You may know ,Dart Is a single threaded system . It's amazing , Your app can do multiple things at the same time , Or at least it looks like that . This is it. The event loop The role of . The event loop Literally, it's an endless cycle of executing scheduled events ( about iOS For developers, it's Run Loop). These events ( Or just code blocks , If you like ) It has to be lightweight , otherwise , Your app will feel sluggish or completely frozen . every last event , If the button is pressed or the network responds , It's all arranged in Event queue in , And wait to be The event loop Receiving and executing . This design pattern in the UI And other systems that handle any type of event Quite common . This concept may be difficult to explain in two sentences , So if you're a beginner , I suggest you watch it nearby thing . Don't think too much , We look at it literally , We're talking about a simple infinite loop and a list of planned tasks ( Code block ), Each iteration of the loop is a .

What we're going to learn about Dart The event loop The special guests at the party are Microtask . our Event Loop There's an extra queue , This is it. Microtask queue . About this queue , The only thing to notice is that , Before the event itself is executed , All the tasks scheduled will be in the The event loop Is executed in an iteration of .

Every iteration starts with all the micro tasks , Then an event is executed . Cycle over and over .

Unfortunately , There is not much information on this , The best explanation I can see is in here or here Found in the network file of .

With this knowledge , Let's look at all the options listed above , Understand how they work and the differences between them .

event

Any entry Event queue Things that are . This is you. Flutter Default method for scheduling asynchronous tasks in . Dispatch a event , Let's add it to Event queue in , from The event loop To receive . This method is widely used Flutter Mechanism use , Such as I/O、 Gesture events 、 Timers, etc .

Timer

Timer yes Flutter The basis of asynchronous tasks in . It's used for scheduling Event queue Code execution in , Is there any delay . The interesting fact is that , If the queue is busy , Your timer will never be executed , Even if it's time .

How to use .

Timer.run(() {
print("Timer");
});
 Copy code 

Future<T> and Future<T>.delayed

A well-known and widely used Dart function . This may come as a surprise , But if you look under the hood , You'll find that it's just the above Timer A package of .

How to use .

Future<void>(() {
print("Future Event");
});
Future<void>.delayed(Duration.zero, () {
print("Future.delayed Event");
});
 Copy code 

Internal implementation ( link ).

factory Future(FutureOr<T> computation()) {
_Future<T> result = new _Future<T>();
Timer.run(() {
try {
result._complete(computation());
} catch (e, s) {
_completeWithErrorCallback(result, e, s);
}
});
return result;
}
 Copy code 

Micro task

As mentioned earlier , All scheduled Micro task It'll be on the next reservation event Before execution . It is recommended to avoid using this queue , Unless you absolutely need to execute code asynchronously , But in Event queue Next event Before . You can also think of this queue as a task queue belonging to the previous event , Because they will be done before the next event . Overloading this queue may completely freeze your application , Because it has to execute everything in the queue first , Only then can we enter the market Event queue Next iteration of , For example, processing user input and even rendering the application itself . For all that , Here's our choice .

scheduleMicrotask

seeing the name of a thing one thinks of its function , stay Micro task queue Scheduling a block code in . Be similar to Timer , If something goes wrong , Will crash the application .

How to use .

scheduleMicrotask(() {
print("Microtask");
});
 Copy code 

Future<T>.microtask

Similar to what we saw before , Take us Micro task Packed in a try-catch In block , Returns execution results or errors in a beautiful and concise way .

How to use .

Future<void>.microtask(() {
print("Microtask");
});
 Copy code 

Internal implementation ( link ).

factory Future.microtask(FutureOr<T> computation()) {
_Future<T> result = new _Future<T>();
scheduleMicrotask(() {
try {
result._complete(computation());
} catch (e, s) {
_completeWithErrorCallback(result, e, s);
}
});
return result;
}
 Copy code 

Back frame callback

The previous two approaches involved low-level The event loop Mechanism , And we're turning now Flutter field . This callback is called when the rendering pipeline completes , So it's with widget Life cycle of . When it is scheduled , It is called only once , Not on every frame . Use addPostFrameCallback Method , You can schedule one or more callbacks , For execution after frame construction is complete . All scheduled callbacks will be executed at the end of the frame in the order they are added . When this callback is called , To ensure the widget Completion of the construction process . Through some smoke and mirrors , You can even visit widget Layout ( RenderBox), Like its size , And do all kinds of other not recommended hackers . The callback itself will run in the normal event queue ,Flutter Almost all events are used by default .

Scheduler binding

This is a drawing callback mixin, The method we are interested in is implemented .

How to use .

SchedulerBinding.instance.addPostFrameCallback((_) {
print("SchedulerBinding");
});
 Copy code 

WidgetsBinding

I specially joined this , Because it's often associated with SchedulerBinding Mentioned together . It is from SchedulerBinding Inherited this method , And there are extra ways that have nothing to do with our subject . Generally speaking , No matter you use SchedulerBinding still WidgetsBinding, Both will be executed SchedulerBinding Exactly the same code in .

How to use .

WidgetsBinding.instance.addPostFrameCallback((_) {
print("WidgetsBinding");
});
 Copy code 

Put our knowledge into practice

Because today we have learned a lot of theoretical knowledge , So I strongly suggest that you play for a while , Make sure you can operate correctly . We can do it before initState Use the following code in , And try to predict its execution order , It doesn't seem to be an easy thing .

SchedulerBinding.instance.addPostFrameCallback((_) {
print("SchedulerBinding");
});
WidgetsBinding.instance.addPostFrameCallback((_) {
print("WidgetsBinding");
});
Timer.run(() {
print("Timer");
});
scheduleMicrotask(() {
print("scheduleMicrotask");
});
Future<void>.microtask(() {
print("Future Microtask");
});
Future<void>(() {
print("Future");
Future<void>.microtask(() {
print("Microtask from Event");
});
});
Future<void>.delayed(Duration.zero, () {
print("Future.delayed");
Future<void>.microtask(() {
print("Microtask from Future.delayed");
});
 Copy code 

Conclusion

Now we know so many details , You can make a thoughtful decision about how to arrange your code . As a rule of thumb , If you need your context or contact Layout or UI Relevant stuff , Use addPostFrameCallback. In any other case , use Future<T> or Future<T>.delayed Scheduling in event queues should be sufficient. . Micro task queue It's a very niche thing , You may never meet them , But it's worth learning . Of course , If your task is heavy , You have to think about creating one Isolate, You may have guessed , This Isolate Will be made by Event queue To convey . But this is the subject of another article . Thank you for your time , See you next time .

Original published in 2021 year 2 month 7 Japan ,https://oleksandrkirichenko.com.


adopt www.DeepL.com/Translator( Free version ) translate

版权声明
本文为[Sunbreak]所创,转载请带上原文链接,感谢
https://qdmana.com/2021/02/20210222134322273T.html

  1. Configure the certificate to enable ngnix to publish the trusted website of HTTPS
  2. Javascript数据类型
  3. HTTP interface debugging tool! 48000 star HTTP command line client!
  4. Parameter encryption of front end URL link band
  5. HTTP interface debugging tool! 48000 star HTTP command line client!
  6. Three front end frameworks: data binding and data flow
  7. Reading Axios source code (1) -- exploring the realization of basic ability
  8. Event bubble and capture in JavaScript
  9. 【微前端】微前端最終章-qiankun指南以及微前端整體探索
  10. R & D solution e-Car front end monitoring system
  11. [JS] 877 - 35 wonderful knowledge of JavaScript, long experience!
  12. R & D solution e-Car front end monitoring system
  13. High performance nginx HTTPS tuning - how to speed up HTTPS by 30%
  14. 解决ajax跨域问题【5种解决方案】
  15. Top ten classic sorting of JavaScript
  16. HTTP 1. X learning notes: an authoritative guide to Web Performance
  17. Vue3 component (IX) Vue + element plus + JSON = dynamic rendering form control component
  18. My http / 1.1 is so slow!
  19. Why Vue uses asynchronous rendering
  20. The response status was 0. Check out the W3C XMLHttpRequest Level 2 spec for
  21. The tapable instance object hook of webpack4. X core tool library
  22. The tapable instance object hook of webpack4. X core tool library
  23. Using libcurl for HTTP communication in C + +
  24. Using libcurl for HTTP communication in C + +
  25. Using CSS variable in Vue
  26. Deeply understand the update of state and props in react
  27. No matter how fast the Internet is, it's useless! In addition to Baidu disk, there is this website slow to let you eat shriveled
  28. Baidu share does not support the solution of HTTPS
  29. [micro front end] the final chapter of micro front end - Qiankun guide and overall exploration of micro front end
  30. [micro front end] the final chapter of micro front end - Qiankun guide and overall exploration of micro front end
  31. Vue cli creates vue3 project
  32. Nginx reverse proxy for windows authentication using NTLM
  33. Rust tutorial: introduction to rust for JavaScript developers
  34. Deploying personal blog to Tencent cloud with serverless framework
  35. R & D solution e-Car front end monitoring system
  36. JavaScript advanced learning
  37. Spend 1 minute to master these 5 ppt tips, courseware making less detours
  38. Vue: vuex persistent state
  39. React native gets the current network state of the device Netinfo
  40. High performance nginx HTTPS tuning - how to speed up HTTPS by 30%
  41. JavaScript advanced: Javascript object-oriented, JavaScript built-in object, JavaScript BOM, JavaScript encapsulation
  42. JavaScript advanced: Javascript object-oriented, JavaScript built-in object, JavaScript BOM, JavaScript encapsulation
  43. Vue determines whether the El form in the elementui is updated or changed. If it changes, it will prompt whether to save it. If it does not change, it will leave directly
  44. Algorithm problem: sum of two numbers -- JavaScript and Java implementation
  45. High performance nginx HTTPS tuning
  46. JQuery advanced
  47. day 30 jQuery
  48. JQuery:JQuery Basic syntax, jQuery selector, jQuery DOM, comprehensive case check box, comprehensive case random picture
  49. TCP/IP 开胃菜 之 HTTP
  50. JQuery:JQuery Basic syntax, jQuery selector, jQuery DOM, comprehensive case check box, comprehensive case random picture
  51. JavaScript data type
  52. [micro front end] the final chapter of micro front end - Qiankun guide and overall exploration of micro front end
  53. Solve Ajax cross domain problem [5 solutions]
  54. HTTP of TCP / IP appetizer
  55. Optimization of pod creation efficiency in serverless scenario
  56. Iqiyi Sports: experience the ultimate expansion and contraction of serverless, and increase the utilization rate of resources by 40%
  57. First knowledge of HTTP / 1.1
  58. First knowledge of HTTP / 1.1
  59. Webpack learning notes series 05 devserver
  60. Webpack learning notes series 04 - resource processing optimization