当App的复杂性发展到一定程度,就会出现一个页面中不同深度的子Widget需要共享访问同一个数据状态,甚至不同页面需要共享同一个状态的情况,这时我们可能会想到InheritedWidget。InheritedWidget是 Flutter 中非常重要的一个功能型组件,它提供了一种在 Widget 树中从上到下共享数据的方式,比如我们在应用的根 Widget 中通过InheritedWidget共享了一个数据,那么我们便可以在任意子Widget 中来获取该共享的数据。而Provider就是对InheritedWidget组件的上层封装,使其更易用,更易复用。具有如下一些特点:
下面我们就来讲讲Flutter官方推荐的Provider状态管理框架如何使用。为了方便讲解和说明,我们使用官方的计数器例子。
dependencies:
flutter:
sdk: flutter
provider: ^6.0.5
import 'package:flutter/foundation.dart';
class CounterProvider with ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
}
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => CounterProvider()),
],
child: MyApp(),
),
);
}
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Count: ${context.watch().count}',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () =>
context.read().increment(),
tooltip: 'Increment',
child: const Icon(Icons.add),
),
),
);
}
}
在上面的示例中,我们访问 CounterProvider 类中的计数变量,就会在有更新时自动重建小部件。通过使用Provider全局状态管理,开发者可以轻松地在Flutter应用程序中实现数据共享。完整的代码如下:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
// Step 1: Create a data provider class
class CounterProvider with ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
}
void main() {
runApp(
// Step 2: Wrap your app with MultiProvider
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => CounterProvider()),
],
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Provider Example',
theme: ThemeData(primarySwatch: Colors.blue),
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Step 3: Use the Consumer widget to access data
return Consumer(
builder: (context, counterProvider, child) {
return Scaffold(
appBar: AppBar(
title: Text('Counter App'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Count:',
style: TextStyle(fontSize: 24),
),
Text(
'${counterProvider.count}',
style: TextStyle(fontSize: 48, fontWeight: FontWeight.bold),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
// Step 4: Trigger state update
counterProvider.increment();
},
child: Icon(Icons.add),
),
);
},
);
}
}