
接下來三天會提到跟狀態管理有關的議題
由於React跟Flutter的核心思想都是State
所以怎麼管理或傳遞這個State就變得非常重要
然後就會衍生出一堆作法/流派(很煩= =)
總之先從簡單的開始吧
今天介紹的是Flutter Widgets 101中
重要性僅次於stless跟stful的InheritedWidget
因為Flutter的特性
UI樹是一層包一層
若底層的widget若想取得上層的state會很麻煩(要一路傳下去)
所以Flutter提供了InheritedWidget
讓底層widget低等下人可以方便取得上層的state
大概像我們以前, 如果有資料大家都要用的話
會用Singleton或是直接寫在AppDelegate XD☘️☘️☘️
InheritedWidget這邊提到的繼承
是Widget樹上的繼承
並不是我們以前物件導向常提到的Class的繼承
而且InheritedWidget是讓人家繼承不是去繼承人家
情境是我們有個神之物件(GodWidget)
若他的心情變了
天空(SkyWidget)的天氣也變了
(是不是跟你的老闆很像 他不爽了我們就要大地震?)
 他不爽了我們就要大地震?)
widget結構如下
實作流程如下(詳見註解)
class GodWidget extends InheritedWidget {
  //官方建議要用final, 這樣你就不能隨便去改它
  final Weather todayWeather;
  
  //因為是要放在上層, 所以建構子一定要有child, 跟你要共享的資料
  GodWidget(this.todayWeather, Widget cho) : super(child: cho);
  //of方法是一個慣例, 代表這個widget是開放給大家取用, 官方建議這麼寫
  static GodWidget of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<GodWidget>();
    //如果用getElementXXX太長的背不起來, 繼承的widget就不會call didChangeDependencies
    //return context.getElementForInheritedWidgetOfExactType<GodWidget>().widget;
  }
  //此widget更新後是否通知其他widget
  @override
  bool updateShouldNotify(InheritedWidget oldWidget) {
    return true;
  }
}
class LessonPageInheritedWidget extends StatefulWidget {
  @override
  _LessonPageInheritedWidgetState createState() => _LessonPageInheritedWidgetState();
}
class _LessonPageInheritedWidgetState extends State<LessonPageInheritedWidget> {
  String currentMood;
  Weather currentWeather;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("第十八堂課"),
          actions: <Widget>[
            DropdownButton(
              hint: Text("心情?"),
              value: null,
              items: [
                DropdownMenuItem(child: Text("大晴天"), value: Weather.sunny),
                DropdownMenuItem(child: Text("下雨天"), value: Weather.rainy),
                DropdownMenuItem(child: Text("做颱風"), value: Weather.typhoon),
                DropdownMenuItem(child: Text("暴風雪"), value: Weather.blizzard),
              ],
              onChanged: (v){
                setState(() {
                  currentWeather = v;
                });
              }
            )
          ],
        ),
        backgroundColor: Colors.red,
          body: GodWidget(currentWeather, SkyWidget())
    );
  }
}
class SkyWidget extends StatefulWidget {
  @override
  _SkyWidgetState createState() => _SkyWidgetState();
}
class _SkyWidgetState extends State<SkyWidget> {
  @override
  Widget build(BuildContext context) {
    Widget widgetIcon(IconData ico){
      return Container(
        alignment: Alignment.center,
        color: Colors.blue,
        child: Icon(ico, color: Colors.white, size: 100),
      );
    }
    switch (GodWidget.of(context).todayWeather) {
      case Weather.sunny:
        return widgetIcon(IcoFontIcons.sunny);
      case Weather.rainy:
        return widgetIcon(IcoFontIcons.rainy);
      case Weather.typhoon:
        return widgetIcon(IcoFontIcons.wind);
      case Weather.blizzard:
        return widgetIcon(IcoFontIcons.snow);
      default:
        return Container(child: null, color: Colors.red);
    }
  }
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    print("天意啊~~~");
  }
}
PS. 不要直接去改InheritedWidget的state(不可對神不敬)
(這位哥的表情真的有戲ww)
下集預告:Provider
最後提供一下github.com/mark33699/IDLF