- 调用setState
- 使用场景:在StatefulWidget内部,当需要更新UI以响应用户交互(如按钮点击)、异步操作完成(如网络请求返回数据)等情况时使用。
- 优点:简单直接,Flutter框架会自动对比新旧状态,仅重新构建需要更新的部分,性能较好。
- 缺点:只能在State类内部调用,若状态更新逻辑在外部(如其他类),需要额外的机制(如回调函数)来传递调用。
- 示例:
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('调用setState示例'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
- 使用InheritedWidget
- 使用场景:当需要在Widget树的多个层级共享数据,并且当数据变化时,使依赖该数据的子孙Widget自动更新。比如应用的主题数据、本地化数据等。
- 优点:可以高效地在Widget树中传递数据,避免在每个层级手动传递数据。
- 缺点:实现相对复杂,需要仔细设计数据结构和依赖关系,若使用不当,可能导致不必要的重建。
- 示例:
class MyInheritedWidget extends InheritedWidget {
final int data;
const MyInheritedWidget({
super.key,
required this.data,
required Widget child,
}) : super(child: child);
static MyInheritedWidget? of(BuildContext context) {
return context.dependOnInheritedWidgetOfExactType<MyInheritedWidget>();
}
@override
bool updateShouldNotify(MyInheritedWidget oldWidget) {
return data != oldWidget.data;
}
}
class MyWidget extends StatelessWidget {
const MyWidget({super.key});
@override
Widget build(BuildContext context) {
final myData = MyInheritedWidget.of(context)?.data;
return Text('Data from InheritedWidget: $myData');
}
}
class InheritedWidgetPage extends StatefulWidget {
const InheritedWidgetPage({super.key});
@override
State<InheritedWidgetPage> createState() => _InheritedWidgetPageState();
}
class _InheritedWidgetPageState extends State<InheritedWidgetPage> {
int _data = 0;
void _updateData() {
setState(() {
_data++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('InheritedWidget示例'),
),
body: MyInheritedWidget(
data: _data,
child: Column(
children: [
const MyWidget(),
ElevatedButton(
onPressed: _updateData,
child: const Text('Update Data'),
),
],
),
),
);
}
}
- 使用Provider
- 使用场景:管理应用状态,适用于中大型应用,可实现数据共享、状态管理等功能,解耦业务逻辑和UI。
- 优点:可实现单向数据流,易于理解和维护,支持依赖注入,方便测试。
- 缺点:引入额外的库,增加了项目复杂度,对于小型应用可能过于复杂。
- 示例:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class CounterModel extends ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
}
class ProviderPage extends StatelessWidget {
const ProviderPage({super.key});
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => CounterModel(),
child: Scaffold(
appBar: AppBar(
title: const Text('Provider示例'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Consumer<CounterModel>(
builder: (context, model, child) {
return Text(
'${model.count}',
style: Theme.of(context).textTheme.headline4,
);
},
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
context.read<CounterModel>().increment();
},
tooltip: 'Increment',
child: const Icon(Icons.add),
),
),
);
}
}
- 使用Bloc模式
- 使用场景:适用于复杂的业务逻辑处理,将业务逻辑与UI分离,提高代码的可维护性和可测试性。
- 优点:实现了清晰的分层架构,业务逻辑集中在Bloc中,便于管理和复用。
- 缺点:开发成本较高,需要编写较多的模板代码,对于简单应用可能显得过于繁琐。
- 示例:
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class CounterCubit extends Cubit<int> {
CounterCubit() : super(0);
void increment() => emit(state + 1);
}
class BlocPage extends StatelessWidget {
const BlocPage({super.key});
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => CounterCubit(),
child: Scaffold(
appBar: AppBar(
title: const Text('Bloc示例'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
BlocBuilder<CounterCubit, int>(
builder: (context, state) {
return Text(
'$state',
style: Theme.of(context).textTheme.headline4,
);
},
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
context.read<CounterCubit>().increment();
},
tooltip: 'Increment',
child: const Icon(Icons.add),
),
),
);
}
}