# Flutter 好用package - provider 介紹 可以幫助你**管理狀態**並通知元件有更新的資料要顯示。這個包允許你為後代的widget提供資料和狀態資訊。而不像標準做法需要每一層都進行傳遞。**用以簡化組件與組件溝通的過程** ``` flutter pub add provider ``` 在App的根層提供Manager變更通知器。這允許子孫小部件訪問標籤管理器。 ![](https://i.imgur.com/UUlrI27.png) ## 範例 ### 建立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`