Flutter_学习记录_数据更新的学习
Flutter 如果界面上有数据更新时,目前学习到的有3种:
- 第一种: 直接用
StatefulWidget
组件,然后当数据更新时,调用setState
的方法更新数据,页面上的数据会直接更新; - 第二种: 用
StatefulWidget
组件 和InheritedWidget
的结合,这种模式比较适用于有比较多层级的场景;这样数据更新时,就不用一层一层的从父类上传递数据; - 第三种:用第三方库
scoped_model
, 这种模式下在StatelessWidget
也可以实现UI页面上数据的更新。
如要实现下面这个页面的效果(点击 count:x 和底部"+", 实现count的数据加1):
1. StatefulWidget 更新数据的使用
这个比较简单,代码如下:
import 'package:flutter/material.dart';
class StatemanagerDemo extends StatefulWidget {
const StatemanagerDemo({super.key});
State<StatemanagerDemo> createState() => _StatemanagerDemoState();
}
class _StatemanagerDemoState extends State<StatemanagerDemo> {
int _count = 0;
void _increaseCount() {
// 这个是关键,只有调用 setState 才能更新页面的数据
setState(() {
_count += 1;
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("StateManagerDemo"),
),
body: CounterWidget(count: _count, increaseCount: _increaseCount),
floatingActionButton: FloatingActionButton(
onPressed: _increaseCount,
child: Icon(Icons.add),
),
);
}
}
class CounterWidget extends StatelessWidget {
final int count;
final VoidCallback increaseCount;
const CounterWidget({super.key, required this.count, required this.increaseCount});
Widget build(BuildContext context) {
return Center(
child: ActionChip(
label: Text("$count"),
onPressed: increaseCount
)
);
}
}
2. StatefulWidget
组件 和 InheritedWidget
的结合
代码如下:
//-------用InheritedWidget 实现数据的更新------
class StateManagerInheriteDemo extends StatefulWidget {
const StateManagerInheriteDemo({super.key});
State<StateManagerInheriteDemo> createState() => _StateManagerInheriteDemoState();
}
class _StateManagerInheriteDemoState extends State<StateManagerInheriteDemo> {
int _count = 0;
void _increaseCount() {
setState(() {
_count += 1;
});
}
Widget build(BuildContext context) {
return CounterProvider(
count: _count,
increaseCount: _increaseCount,
child: Scaffold(
appBar: AppBar(
title: Text("StateManagerDemo"),
),
body: CounterWidgetInherite(),
floatingActionButton: FloatingActionButton(
onPressed: _increaseCount,
child: Icon(Icons.add),
),
)
);
}
}
// 创建一个provider类来提供全局可用的数据存储和获取
class CounterProvider extends InheritedWidget {
final int count;
final VoidCallback increaseCount;
final Widget child;
const CounterProvider({super.key, required this.count, required this.increaseCount, required this.child}) : super(child: child);
// 定义一个of方法,可以获取CounterProvider的数据
static CounterProvider? of(BuildContext context) => context.dependOnInheritedWidgetOfExactType<CounterProvider>();
bool updateShouldNotify(covariant InheritedWidget oldWidget) {
return true;
}
}
// 模拟多个层级1
class CounterWidgetInherite extends StatelessWidget {
const CounterWidgetInherite ({super.key});
Widget build(BuildContext context) {
return Center(
child: Counter(),
);
}
}
// 模拟多个层级2
class Counter extends StatelessWidget {
const Counter({super.key});
Widget build(BuildContext context) {
final int? count = CounterProvider.of(context)?.count;
final VoidCallback? increaseCount = CounterProvider.of(context)?.increaseCount;
return ActionChip(
label: Text("$count"),
onPressed: increaseCount,
);
}
}
3. scoped_model 的使用
scoped_model
是第三方库,需要在项目中引入三方库(引入三方库的方法,参考这个文章);其次,该模式引用到的组件主要是:
ScopedModel
ScopedModelDescendant
原理还没搞明白,只是看着视频实现了功能,代码如下:
import 'package:flutter/material.dart';
import 'package:scoped_model/scoped_model.dart';
//-------用Scoped_Model 实现数据的更新-----
class StateManagerScopteModelDemo extends StatelessWidget {
const StateManagerScopteModelDemo({super.key});
Widget build(BuildContext context) {
// 用ScopedModel 包装一下,提供model属性对应的类型
return ScopedModel(
model: CounterModel(),
child: Scaffold(
appBar: AppBar(
title: Text("StateManagerDemo"),
),
body: CounterWidgetScopteModel(),
// ScopedModelDescendant 的构建方法获取CounterModel对应的数据
floatingActionButton: ScopedModelDescendant<CounterModel>(
rebuildOnChange: false,
builder: (context, _, model) {
return FloatingActionButton(
onPressed: model.increaseCount,
child: Icon(Icons.add),
);
}
),
)
);
}
}
class CounterWidgetScopteModel extends StatelessWidget {
const CounterWidgetScopteModel ({super.key});
Widget build(BuildContext context) {
return Center(
// ScopedModelDescendant 的构建方法获取CounterModel对应的数据
child: ScopedModelDescendant<CounterModel>(
builder: (context, _, model) {
return ActionChip(
label: Text("count: ${model.count}"),
onPressed: model.increaseCount,
);
}
),
);
}
}
// 创建继承于Model的业务类,来存放对应的count和用到的方法
class CounterModel extends Model {
int _count = 0;
int get count => _count;
void increaseCount() {
_count += 1;
// 使用Model小部件的地方会监听Model的变化,可以用notifyListeners方法重建UI
notifyListeners();
}
}