iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 21
1
Mobile Development

iOS Developer Learning Flutter系列 第 21

iOS Developer Learning Flutter. Lesson20 InheritedWidget

Today Preview

前言

接下來三天會提到跟狀態管理有關的議題
由於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結構如下

  • LessonPageInheritedWidget
    • appBar:DropdownButton
    • body:GodWidget
      • SkyWidget

實作流程如下(詳見註解)

  1. 建立InheritedWidget(造神)
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;
  }

}
  1. 把InheritedWidget放在最上方(請神)
    先把GodWidget做為body的root
    然後利用LessonPageInheritedWidget管理子widget的狀態
    當appBar的DropdownButton改變後
    就把state傳給GodWidget
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())
    );
  }
}
  1. 取得InheritedWidget的狀態(拜神)
    先在build裡面透過of取得GodWidget的todayWeather
    若InheritedWidget更新了
    就會call didChangeDependencies
    然後再call一次build
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


上一篇
iOS Developer Learning Flutter. Lesson19 Life Cycle
下一篇
iOS Developer Learning Flutter. Lesson21 Provider
系列文
iOS Developer Learning Flutter30

尚未有邦友留言

立即登入留言