Flutter自带管理组件
1管理状态的最常见的方法:
方法 | 描述 |
自身状态管理 | Widget管理自己的状态。 |
父组件管理子组件状态 | 父Widget管理子Widget状态。 |
混合管理 | 混合管理(父Widget和子Widget都管理状态)。 |
全局状态管理 | 使用第三方库进行全局状态管理 |
关于状态管理原则:
- 如果状态是用户数据,如复选框的选中状态、滑块的位置,则该状态最好由父Widget管理。
- 如果状态是有关界面外观效果的,例如颜色、动画,那么状态最好由Widget本身来管理。
- 如果某一个状态是不同Widget共享的则最好由它们共同的父Widget管理。
建议:
在Widget内部管理状态封装性会好一些,而在父Widget中管理会比较灵活。有些时候,如果不确定到底该怎么管理状态,那么推荐的首选是在父widget中管理(灵活会显得更重要一些)。
2.组件自身管理自身状态
自己管理自己的状态比较简单, 参数在组件内部 , 同时 setState也在自己内部
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("组件自己管理自己状态"),
),
body: SelfWidget(),
);
}
}
class SelfWidget extends StatefulWidget {
@override
_SelfWidgetState createState() => _SelfWidgetState();
}
class _SelfWidgetState extends State<SelfWidget> {
bool _isActive = false;
_handleTap() {
setState(() {
_isActive = !_isActive;
});
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: _handleTap,
child: Container(
width: 200,
height: 200,
color: _isActive ? Colors.amber : Colors.blueAccent,
),
);
}
}
3. 父组件管理子组件
父组件将参数和方法传给子组件供子组件调用, 子组件调用方法其实是在父组件中setState了.
子组件可以是无状态组件, 因为它并没有管理自身状态
说明形成条件:
- 1.父组件必须是StatefulWidget
- 2.父组件将参数和方法传给子组件供子组件调用
- 3.子组件调用方法是父组件的函数(函数中写有setState),否则子组件StateLessWidget是不生效的
总结:简单说,子组件的OnTap方法,执行的函数是父组件的,父组件进行回调
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("父组件管理子组件状态"),
),
body: ParentsWidget(),
);
}
}
class ParentsWidget extends StatefulWidget {
@override
_ParentsWidgetState createState() => _ParentsWidgetState();
}
class _ParentsWidgetState extends State<ParentsWidget> {
bool _isActive = false;
void _tapToChangeColor(v) {
setState(() {
_isActive = v;
});
}
@override
Widget build(BuildContext context) {
return SonWidget(isActive: _isActive, tapFunction: _tapToChangeColor);
}
}
class SonWidget extends StatelessWidget {
final bool isActive;
final Function tapFunction;
SonWidget({Key key, this.isActive, this.tapFunction}) : super(key: key);
void _handleTap() {
tapFunction(!isActive);
}
@override
Widget build(BuildContext context) {
return Center(
child: GestureDetector(
child: Container(
width: 200,
height: 200,
color: isActive ? Colors.amber : Colors.blue,
),
onTap: _handleTap,
),
);
}
}
4.混合管理
子组件是有状态组件, 那么它可被父组件管理, 也可以自己管理自己.
说明形成条件:
- 1.父组件必须是StateFulWidget
- 2.子组件必须是StateFulWidget
总结:父组件接管子组件一部分状态, 子组件再自己管理一些仅与自己相关的状态
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("混合管理"),
),
body: ParentsWidget(),
);
}
}
class ParentsWidget extends StatefulWidget {
@override
_ParentsWidgetState createState() => _ParentsWidgetState();
}
class _ParentsWidgetState extends State<ParentsWidget> {
bool _isActive = false; //这个状态是父组件管理的, 给子组件用
void _tapToChangeColor(v) {
setState(() {
_isActive = v; //父组件接管管理的状态在此更新
});
}
@override
Widget build(BuildContext context) {
return SonWidget(isActive: _isActive, tapFunction: _tapToChangeColor);
}
}
class SonWidget extends StatefulWidget {
final bool isActive;
final Function tapFunction;
SonWidget({Key key, this.isActive, this.tapFunction}) : super(key: key);
@override
_SonWidgetState createState() => _SonWidgetState();
}
class _SonWidgetState extends State<SonWidget> {
bool _borderHighLight = false; //这个状态是自己管理的
void _handleTap() {
widget.tapFunction(!widget.isActive); //这个状态是父组件管理的
setState(() {
_borderHighLight = !_borderHighLight; //自己管理的状态在此更新
});
}
@override
Widget build(BuildContext context) {
return Center(
child: GestureDetector(
child: Container(
width: 200,
height: 200,
child: Container(
color: widget.isActive ? Colors.amber : Colors.blueAccent,
),
decoration: BoxDecoration(
border: Border.all(
color: _borderHighLight ? Colors.blueAccent : Colors.amber,
width: 10)),
),
onTap: _handleTap,
),
);
}
}