textfield reload issue and other things reload problem.===================================
https://github.com/flutter/flutter/issues/18828
https://blog.csdn.net/u011272795/article/details/83010974 <<<<<<<===============
https://medium.com/saugo360/flutter-my-futurebuilder-keeps-firing-6e774830bc2
Flutter: My FutureBuilder Keeps Firing!
If you’ve ever done any serious Flutter development, then you have definitely faced the problem in the title above. But don’t worry, You’re not alone!
What is the problem?
The FutureBuilder
widget that Flutter provides us to create widgets based on the state of some future, keeps re-firing that future every time a rebuild happens! The problem is best manifested with this simple example:
void main() => runApp(MyApp()); class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomeScreen()
);
}
} class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
} class _HomeScreenState extends State<HomeScreen> { bool _switchValue; @override
void initState() {
super.initState();
this._switchValue = false;
} @override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Switch(
value: this._switchValue,
onChanged: (newValue) {
setState(() {
this._switchValue = newValue;
});
},
),
FutureBuilder(
future: this._fetchData(),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
return Center(
child: CircularProgressIndicator()
);
default:
return Center(
child: Text(snapshot.data)
);
}
}
),
],
),
);
} _fetchData() async {
await Future.delayed(Duration(seconds: 2));
return 'REMOTE DATA';
}
}
- Our app displays a
HomeScreen
on which we have oneSwitch
widget and oneFutureBuilder
that loads remote data and displays it on the screen. - The
FutureBuilder
subscribes to the future returned from the function_fetchData
. This function simulates a server that returns its result after two seconds. - When the user taps the switch, we update the member
_switchValue
, which is then fed into the switch itself, to change its actual value.
If you run this app, the following happens:
Flipping the switch affects the state of the FutureBuilder
Even though the switch and the FutureBuilder are not related in any form, every time we change the switch value (by calling setState
), the FutureBuilder
goes through its whole life-cycle again! It re-fetches the future, causing unneeded traffic, and shows the loading again, causing bad user experience.
This problem manifests itself in a variety of ways. In some cases it’s not even as obvious as the example above. For example:
- Network traffic being generated from pages that are not currently on screen
- Hot reloading not working properly
- Losing the Navigator state when updating values in some Inherited Widgets
- etc…
But what is the cause of all of this? And how can we solve it?
The didUpdateWidget problem
Note: In this section I will take a closer look at how FutureBuilder works. If you’re not interested in this, you can skip to the solution.
If we take a closer look at the code of FutureBuilder
, we find that it is a StatefulWidget
. As we know, StatefulWidgets
maintain a long-livedState
object. This state has a few methods that manage its life-cycle, like initState
, build
, and didUpdateWidget
. initState
is called only once when the state object is first created, and build
is called every time we need to build the widget to display, but what what about didUpdateWidget
? This method is called whenever the widget attached to this State object changes. When the widget is rebuilt with new inputs, the old widget is disposed, and a new widget is created and assigned to the State object, and didUpdateWidget
is called to do anything we want to do before the rebuild. In case of FutureBuilder
, this method looks like this:
@override
void didUpdateWidget(FutureBuilder<T> oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.future != widget.future) {
if (_activeCallbackIdentity != null) {
_unsubscribe();
_snapshot = _snapshot.inState(ConnectionState.none);
}
_subscribe();
}
}
It’s basically saying: if, when rebuilt, the new widget has a different Future instance than the old one, then repeat everything: unsubscribe, and subscribe again.
Well, that’s the key! If we provide it with the same future, then it will not refire!
But aren’t we providing the same future? we’re calling the same function! well, it’s not the same future instance. Our function is doing exactly the same work, but then returning a new future, different from the old one.
So, what we want to do is to store or cache the output of the function the first time it is called, and then provide this same output whenever the function is called again. This process is known as memoization.
Solution: Memoize the future
Memoization is, in simple terms, caching the return value of a function, and reusing it when that function is called again. Memoization is mostly used in functional languages, where functions are deterministic (they always return the same output for the same inputs), but we can use simple memoization for our problem here, to make sure the FutureBuilder
always receives the same future instance.
To do that, we will use Dart’s AsyncMemoizer
. This memoizer does exactly what we want! It takes an asynchronous function, calls it the first time it is called, and caches its result. For all subsequent calls to the function, the memoizer returns the same previously calculated future.
Thus, to solve our problem, we start by creating an instance of AsyncMemoizer
in our widget:
final AsyncMemoizer _memoizer = AsyncMemoizer();
Note: you shouldn’t instantiate the memoizer inside a StatelessWidget
, because Flutter disposes of StatelessWidgets
at every rebuild, which basically beats the purpose. You should instantiate it either in a StatefulWidget, or somewhere where it can persist.
Afterwards, we will modify our _fetchData
function to use that memoizer:
_fetchData() {
return this._memoizer.runOnce(() async {
await Future.delayed(Duration(seconds: 2));
return 'REMOTE DATA';
});
}
- We wrapped our function with
AsyncMemoizer.runOnce
which does exactly what it sounds like; it runs the function only once, and when called again, returns the cached future.
And that’s it! Our FutureBuilder
now only fires the first time around:
Thus, our FutureBuilder
was getting confused, and thinking that a new future was passed to it, causing it to refire every time. To solve this, we used Dart’s AsyncMemoizer
to pass the same future instance every time.
I hope this has been helpful! Let me know what you think!
textfield reload issue and other things reload problem.===================================的更多相关文章
- eclipse 打开是报错"reload maven project has encountered a problem"
不需要删除整个 .metadata 如果删除这个代价是重新导入全部项目 D:\eclipse-workspace\.metadata\.plugins\org.eclipse.e4.workbench ...
- 在IE浏览器中执行OpenFlashChart的reload方法时无法刷新的解决方法
由于项目需求,需要在网页上利用图表展示相关数据的统计信息,采用了OpenFlashChart技术.OpenFlashChart是一款开源的以Flash和Javascript为技术基础的免费图表,用它能 ...
- javascript 中的location.reload
location.reload()是什么意思 location.reload() 括号内有一个参数 true/false , 为空和false的效果一样. 如果该方法没有规定参数,或者参数是 fals ...
- 把Nginx加入系统服务 service nginx (start | stop | restart | reload)
vim /etc/init.d/nginx 1 #!/bin/bash 2 # nginx Startup script for the Nginx HTTP Server 3 # it is v ...
- 使用Tomcat的Reload提高开发速度(翻译)
欢迎转载http://www.cnblogs.com/coodream2009,有翻译的不太准确的地方请大家指出,我继续修改完善. 按照Java Servlet规范第四部分推荐的,Tomcat系统的实 ...
- layui table数据表格reload where参数保留问题
layui table数据表格reload where参数保留问题 在使用layui过程中多多少少会遇到些问题 table reload 有个坑:reload时where参数会保留上次的参数,如果用 ...
- javascript:location.reload()和location.replace()的区别,及对图片缓存的影响。
有段时间没有清理IE的临时文件(缓存文件),在我清理的时候,我突然发现一个问题. 我打开的一个网站,图片默认缓存一个月的,但我发现,当我上传图片或删除图片之后,图片重新缓存,也就意味着,在我上传新图片 ...
- Python中的reload函数
Python中的import语句可以导入module文件,但是import语句只是第一次导入的时候会执行module文件中的代码,然后就会把导入的模块文件存入到内存,当再次导入的时候,Python是直 ...
- python之reload用法
一.python2和python3的区别 python2中可以直接使用reload().python3中需要从库中导入,有两种方法: >>> from imp import relo ...
随机推荐
- gitIgnore说明
有些内容不需要提交到git服务器上,这时我们可以配置.gitIgnore文件.可参考:https://www.cnblogs.com/kevingrace/p/5690241.html 可能有时候你会 ...
- Linux技术栈整理一:系统体系结构
Linux操作系统必备的硬件构造: CPU 主板 显卡 硬盘 网卡 外设(键鼠-输入设备 / 显示器-输出设备) 内核管理调度: 内核体系结构: 来源于:极客专栏
- ASO的效果应该如何去评判,有什么标准可以量化指标
ASO的效果应该如何去评判,有什么标准可以量化指标 以往我们主要会教大家怎么做 ASO 优化,优化中有什么技巧……在掌握ASO优化技巧之后,从执行层面来考虑,就该选择流量平台了. 目前市场上的流量平台 ...
- Windows bat批处理使用
mkdir commonmkdir datamkdir savemkdir data\tsushima_m_mapmkdir save\tsushima_m_map msxsl ..\common\r ...
- 转 linux安装jdk环境(多种方式)
linux系统通用安装通过tar.gz压缩包安装此方法适用于绝大部分的linux系统 1.先下载tar.gz的压缩包,这里使用官网下载. 进入: http://www.oracle.com/techn ...
- tcprstat测试服务器请求响应时间
tcprstat使用,tcprstat必须使用root权限才能使用 tcprstat -p 3306 -t 1 -n 5 -l 192.168.52.250 centos统计分析所有的IP地址
- CF653F Paper task
题目链接:洛谷 首先我们不考虑本质不同这个限制. 既然不能直接用栈乱搞,我们就可以用一个前缀和的套路了. 我们将(设为1,将)设为-1,记前缀和为$s_i$,则$[i,j]$这一段是回文子串当且仅当 ...
- KMP初步
KMP算法专门用于处理字符串匹配问题. 开始学习的时候觉得很有道理,但是一些细节总觉得有些模糊,所以一直觉得懵懵懂懂.今天思考了一下,总结一下,希望对大家也有帮助. 朴素的字符串匹配算法就是一个一个字 ...
- Cocos Creator JS 获取当前日期与时间
var testDate = new Date(); testDate.getYear();//获取当前年份(2位) testDate.getFullYear(); //获取完整的年份(4位,1970 ...
- HDFS之HA
HDFS高可用环境HA的架构 HDFS组件由一个对外提供服务的namenode(存储元数据)和N个datanode组成:Zookeeper有三个作用:1.为了统一配置文件 config 2.多个节点的 ...