# Flutter 好用package - provider 介紹
可以幫助你**管理狀態**並通知元件有更新的資料要顯示。這個包允許你為後代的widget提供資料和狀態資訊。而不像標準做法需要每一層都進行傳遞。**用以簡化組件與組件溝通的過程**
```
flutter pub add provider
```
在App的根層提供Manager變更通知器。這允許子孫小部件訪問標籤管理器。

## 範例
### 建立Manager
Manager擴充套件了ChangeNotifier。這允許該物件向其監聽器提供變化通知。
呼叫notifyListeners()來通知所有監聽此狀態的部件。
```dart
class TabManager extends ChangeNotifier {
int selectedTab = 0; //當前
void goToTab(index) {
selectedTab = index;
notifyListeners();
}
void goToRecipes() {
selectedTab = 1;
notifyListeners();
}
}
```
### 建立一個TabManager 的 Provider
在App的根層提供TabManager變更通知器。這允許子孫小部件訪問標籤管理器。把MultiProvider指定為Home的一個屬性。這接受了一個供Home的後代部件訪問的提供者列表。
ChangeNotifierProvider建立一個TabManager的例項,它監聽標籤索引的變化並通知其監聽者。
```dart
//main.dart
Widget build(BuildContext context) {
final theme = FooderlichTheme.light();
return MaterialApp(
theme: theme,
title: 'Fooderlich',
home: MultiProvider(
providers: [
ChangeNotifierProvider(
create: (context) => TabManager(),
),
],
child: const Home(),
),
);
}
```
### 新增一個TabManager 的 consumer
設定消費者了,這樣應用程式就可以收聽TabManager廣播的變化。
把所有的小部件都包裹在Consumer裡面。當TabManager改變時,它下面的widget將重建。 根據當前的標籤索引,顯示正確的頁面小部件。
```dart
class _HomeState extends State<Home> {
static List<Widget> pages = <Widget>[
const ExploreScreen(),
RecipesScreen(),
const GroceryScreen()
];
@override
Widget build(BuildContext context) {
return Consumer<TabManager>(
builder: (context, tabManager, child) {
return Scaffold(
appBar: AppBar(
title: Text('Fooderlich',
style: Theme.of(context).textTheme.headline6),
),
body: pages[tabManager.selectedTab],
bottomNavigationBar: BottomNavigationBar(
selectedItemColor:
Theme.of(context).textSelectionTheme.selectionColor,
currentIndex: tabManager.selectedTab,
onTap: (index) {
tabManager.goToTab(index);
},
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.explore),
label: 'Explore',
),
BottomNavigationBarItem(
icon: Icon(Icons.book),
label: 'Recipes',
),
BottomNavigationBarItem(
icon: Icon(Icons.list),
label: 'To Buy',
),
],
),
);
},
);
}
}
```
### 子元件使用
listen 如果給 false 可以讓他不監聽 notifyListeners 而重新渲染,常用在如果只是想調用一個 function 時可以使用,避免不必要的重新渲染。
```dart
Provider.of<TabManager>(context, listen: false).goToRecipes();
```
## 延伸教學 Navigator
[Navigator 介紹](https://hackmd.io/@BzWzq-x9Rb2G4WG03gcyKg/rk1ci8lc5)
###### tags: `flutter`