Provider是flutter官方提供的用来进行状态管理的一个框架,简单的可以理解为,当一个数据对象变化时,我们希望UI中能同步的更新,它能自动的监听变化,避免了手动调用的过程。
首先导入依赖
dependencies:
provider: ^6.0.3
它的原理其实还是观察者模式,在最顶层的widget上包裹一个Provider,创建出我们需要监听的数据,在子widget中就可以拿到变化的数据。
1、创建一个被观察的对象,这个类中包含了我们所需要监听的数据
class Counter with ChangeNotifier{
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
}
2、在最顶层的widget,用一个Provider包裹起来
child: ChangeNotifierProvider<Counter>(create: (_)=>Counter(),child: MyApp(),)
// 上面是用范型的方式指定数据对象,也可以用下面的这种方式
child: ChangeNotifierProvider.value(
value: Counter(),
child: MyApp()
),
注意,这里不要使用Provider,因为它不会更新UI,要使用ChangeNotifierProvider或者是
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => Counter()),
],
child: const MyApp(),
),
如果有多个对象就用上面这种。
3、在要使用的地方将其取出来
floatingActionButton: FloatingActionButton(
key: const Key('increment_floatingActionButton'),
/// Calls `context.read` instead of `context.watch` so that it does not rebuild
/// when [Counter] changes.
onPressed: () => context.read<Counter>().increment(),
tooltip: 'Increment',
child: const Icon(Icons.add),
),
上面一个是context.read, 这样widget不会被重建,在需要改变的地方就要用context.watch了
Widget build(BuildContext context) {
return Text(
/// Calls `context.watch` to make [Count] rebuild when [Counter] changes.
'${context.watch<Counter>().count}',
key: const Key('counterState'),
style: Theme.of(context).textTheme.headline4);
}
也可以用下面的这种方式
Widget build(BuildContext context) {
var counter = Provider.of<Counter>(context);
return Text(
/// Calls `context.watch` to make [Count] rebuild when [Counter] changes.
'${counter.count}',
key: const Key('counterState'),
style: Theme.of(context).textTheme.headline4);
}
不过上面的这种方式不推荐使用,因为刷新的时候其他的子widget也会跟着一起刷新,比较影响性能。
或者用Consumer的方式
Widget build(BuildContext context) {
return Consumer<Counter>(builder: (_,counter,child){
return Text(counter.count.toString());
});
}
综上来看,还是context.watch和Consumer的方式要简单一些。
Selector
上面我们说了Consumer,Selector其实和Consumer差不多,只是Consumer处理的是一个对象,但是Selector处理的更精细一些,它可以处理一个对象中的某些成员,过滤掉一些不关心的数据,还是以上面的例子,我们将Counter改成
class Counter with ChangeNotifier{
int _count = 0;
String _name = "";
int get count => _count;
String get name => _name;
void increment() {
_count++;
notifyListeners();
}
void setName(){
_name += "a";
notifyListeners();
}
}
增加了一个name字段,下面通过一个Selector来监听它的变化
class NameWidget extends StatelessWidget {
const NameWidget({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return Selector<Counter, String>(
builder: (_, name, child){
return Text(name);
},
selector: (_, counter) => counter.name,);
}
}
Selector也是一个范型类,需要传入对象和成员的类型Counter, String,然后在它的selector函数中选择需要处理的成员,在builder中构建一个Widget返回。
timer不需要再导入就来就可以使用了,一般我们就用它来做两件事情
1、每隔一定的时间去做一件事,周期性执行
2、一段时间后执行,只执行一次。
下面看一下它的用法
1、5s后执行
Timer timer1 = Timer(const Duration(seconds: 5), (){
print("dosomething");
});
2、每隔1s执行一次
timer = Timer.periodic(const Duration(seconds: 1), (timer) {
_setNowTime();
});
需要注意的是Timer在创建完成后就开始计时了,不需要再调用start()之类的方法, 需要取消时调用timer.cancel()取消, 第二个参数是一个回调函数。
Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/
我有两个Rails模型,即Invoice和Invoice_details。一个Invoice_details属于Invoice,一个Invoice有多个Invoice_details。我无法使用accepts_nested_attributes_forinInvoice通过Invoice模型保存Invoice_details。我收到以下错误:(0.2ms)BEGIN(0.2ms)ROLLBACKCompleted422UnprocessableEntityin25ms(ActiveRecord:4.0ms)ActiveRecord::RecordInvalid(Validationfa
目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称
最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总
深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal
我正在尝试将以下SQL查询转换为ActiveRecord,它正在融化我的大脑。deletefromtablewhereid有什么想法吗?我想做的是限制表中的行数。所以,我想删除少于最近10个条目的所有内容。编辑:通过结合以下几个答案找到了解决方案。Temperature.where('id这给我留下了最新的10个条目。 最佳答案 从您的SQL来看,您似乎想要从表中删除前10条记录。我相信到目前为止的大多数答案都会如此。这里有两个额外的选择:基于MurifoX的版本:Table.where(:id=>Table.order(:id).
我目前正在用Ruby编写一个项目,它使用ActiveRecordgem进行数据库交互,我正在尝试使用ActiveRecord::Base.logger记录所有数据库事件具有以下代码的属性ActiveRecord::Base.logger=Logger.new(File.open('logs/database.log','a'))这适用于迁移等(出于某种原因似乎需要启用日志记录,因为它在禁用时会出现NilClass错误)但是当我尝试运行包含调用ActiveRecord对象的线程守护程序的项目时脚本失败并出现以下错误/System/Library/Frameworks/Ruby.frame
我有一个应用需要发送用户事件邀请。当用户邀请friend(用户)参加事件时,如果尚不存在将用户连接到该事件的新记录,则会创建该记录。我的模型由用户、事件和events_user组成。classEventdefinvite(user_id,*args)user_id.eachdo|u|e=EventsUser.find_or_create_by_event_id_and_user_id(self.id,u)e.save!endendend用法Event.first.invite([1,2,3])我不认为以上是完成我的任务的最有效方法。我设想了一种方法,例如Model.find_or_cr
我完全不是程序员,正在学习使用Ruby和Rails框架进行编程。我目前正在使用Ruby1.8.7和Rails3.0.3,但我想知道我是否应该升级到Ruby1.9,因为我真的没有任何升级的“遗留”成本。缺点是什么?我是否会遇到与普通gem的兼容性问题,或者甚至其他我不太了解甚至无法预料的问题? 最佳答案 你应该升级。不要坚持从1.8.7开始。如果您发现不支持1.9.2的gem,请避免使用它们(因为它们很可能不被维护)。如果您对gem是否兼容1.9.2有任何疑问,您可以在以下位置查看:http://www.railsplugins.or
在许多ruby类之间共享记录器实例的最佳(正确)方法是什么?现在我只是将记录器创建为全局$logger=Logger.new变量,但我觉得有更好的方法可以在不使用全局变量的情况下执行此操作。如果我有以下内容:moduleFooclassAclassBclassC...classZend在所有类之间共享记录器实例的最佳方式是什么?我是以某种方式在Foo模块中声明/创建记录器还是只是使用全局$logger没问题? 最佳答案 在模块中添加常量:moduleFooLogger=Logger.newclassAclassBclassC..