iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 16
0
Mobile Development

用 Flutter 開發一個 Android App 吧系列 第 16

用 Flutter 開發一個 Android App 吧 - Day 16. 題外話、活動頁(改)及議題頁(改)

  • 分享至 

  • xImage
  •  

本系列同步發表在 個人部落格,歡迎大家關注~


題外話

到昨天,本人就撐完此系列的一半了,可喜可賀~

不過在這資訊時代,難免會在意自己文章被別人閱讀的想法或次數,簡單來說就是流量
我是正式開賽後隔一個禮拜才開始發文,一開始覺得這主題(Mobile Development)好像沒太多人關注,好幾個參賽者跟我一樣,最多也才一、兩百瀏覽次數。

結果在 9/17 這主題的熱門文章突然間殺出一篇 5000+ 瀏覽次數的,

我當場直接
傻爆眼 ... /images/emoticon/emoticon26.gif

哇靠! 是一夜之間從哪裡烙這麼多人來點閱的... 莫非是哪位超級大神寫的文 !?
我花這麼長時間準備才寫出一篇 100+ 瀏覽次數,不免有些氣餒阿... /images/emoticon/emoticon20.gif

雖然知道 ithelp 有這方面的 Bug,但我看之前幾屆好像都沒這麼誇張...
後來在 9/20 這主題由 badgameshowtw 發出 [Day 4] Xcode安裝 為什麼有5000觀看??? ithelp觀察實驗 這篇文刷了十幾萬瀏覽後, ithelp 有人開始修正這問題。

好拉,這題外話算是有些抱怨,也希望評分沒有過度參考這數據。
當然期望 ithelp 有更好的機制,也勉勵其他跟我一樣的參賽者能堅持下去,為社群貢獻出優質文章囉~ /images/emoticon/emoticon69.gif


好了,正篇開始

活動頁 - 改 (待補)

如果你看自己的 github.com 首頁,就會顯示所有的活動。

基本上活動頁就是此頁面的 App 版,研究之後應該是調用 GitHub REST API v3 - Feeds 這個 API。

不過我所使用的 github 套件似乎還沒整合這個 API;內容之後補上。

內容待補
如果一直沒人實現這部份,或許有時間我會發個 PR 給作者吧

議題頁 - 改

接著我直接修改議題頁拉~
其實跟昨天的 [倉庫頁 - 改],差不多概念;一樣使用 FutureBuilder 、修改 issueList 、實現 fetchIssues() 函數。

lib/pages/issue.dart

  ...

  @override
  Widget build(BuildContext context) {
    return Scrollbar(
      child: RefreshIndicator(
        child: FutureBuilder(
          future: issueList,
          builder: (BuildContext context, AsyncSnapshot<List<Issue>> snapshot) {
            switch (snapshot.connectionState) {
              case ConnectionState.done:
                if (!snapshot.hasError) {
                  return ListView.separated(
                    itemCount: snapshot.data.length,
                    itemBuilder: (BuildContext context, int index) {
                      final now = DateTime.now();
                      final difference =
                          now.difference(snapshot.data[index].createdAt);
                      var createTimeAgo =
                          timeago.format(now.subtract(difference));

                      return ListTile(
                        dense: true,
                        leading: CircleAvatar(
                          radius: 18.0,
                          backgroundImage:
                              NetworkImage(snapshot.data[index].user.avatarUrl),
                        ),
                        title: Text(snapshot.data[index].title),
                        subtitle: Text(createTimeAgo),
                        trailing: Icon(Icons.error_outline),
                        onTap: () {},
                      );
                    },
                    separatorBuilder: (BuildContext context, int index) =>
                        const Divider(height: 0.0),
                  );
                } else {
                  return Center(child: Text("No Data"));
                }
                break;
              case ConnectionState.none:
              case ConnectionState.active:
              case ConnectionState.waiting:
                return Center(child: CircularProgressIndicator());
            }
          },
        ),
        onRefresh: () async {
          await Future.delayed(Duration(seconds: 1));
          setState(() {
            issueList = fetchIssues();
          });
        },
      ),
    );
  }
  
  Future<List<Issue>> fetchIssues() async {
    return githubClient.issues.listAll(state: "all").toList();
  }

對比昨天的程式碼是不是 87 分像阿~

小提醒:

--

成果

day16-1.gif

Flutter State 的生命週期

大致改完所有首頁的內容後,我覺得應該來講一下 State 的生命週期。

說是「生命週期」,其實就是從(預備)創建畫面、顯示畫面、離開畫面,其中過程調用到的函數。

我直接找別人整理好的附圖,直接看右半邊的部份。

flutter-life-cycle

參考自 https://blog.duicode.com/3108.html
左半邊為 Android App 的生命週期。

可能大家可以看得出來繼承 StatefulWidget 的 Widget 在程式碼最大的特點,就是會重寫(override) createState() 這個函數。

createState() 開啟 State 的生命週期,而我個人最常用到的函數為 intState()build()dispose()setState()

State 物件有著以下的生命週期:

  • 框架(Flutter)會藉由調用 StatefulWidget.createState 方法建造一個 State 物件。
  • 每個新建出來的 State 物件會永久對應一個 BuildContext ,但 State 物件並不會改變 BuildContext。此時會將 State 物件標記成為 mounted(mounted=true) 狀態。
  • 調用 initState,可藉由重寫(override) initState 來初始化設定。
  • 調用 didChangeDependencies
  • 此時 State 物件已做好全面初始化,接下來調用 build 方法來建構 UI。State 物件可藉由 setState 方法來重建或調整 UI。
  • 在重建或調整 UI 的過程中,State 物件會先調用 didUpdateWidget 方法看有沒有對應的 Widget 需要作改變,didUpdateWidget 之後一定會再調用 build 方法(意味著在 didUpdateWidget 內用 setState 是沒意義的)。
  • 在開發過程中,熱重載會調用 reassemble 方法。
  • State 物件從 Tree 中被移除會調用 deactivate 方法。
  • 如果 State 物件有插入至其他 Subtree 會調用 build 方法,否則會調用dispose 方法。
  • 當調用 dispose 方法後,State 物件會被標記成 unmounted (mounted=false),生命週期就此結束。

不負責之簡易翻譯https://api.flutter.dev/flutter/widgets/State-class.html

--

小提醒:

  • State 生命週期過程中其實有很多細節,礙於全部翻譯出來會很冗長,所以我只挑重點部份翻譯,詳細的話還是得要讀官方文件。
  • 小弟也是讀了文件後才更深入的理解 "State"fulWidget 中的祕密。

上一篇
用 Flutter 開發一個 Android App 吧 - Day 15. GitHub API 初體驗、倉庫頁(改)
下一篇
用 Flutter 開發一個 Android App 吧 - Day 17. 搜尋頁面(改)、自製 GitHub Tiles
系列文
用 Flutter 開發一個 Android App 吧30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

1
Robby
iT邦新手 5 級 ‧ 2020-01-25 15:23:44

小弟菜鳥,一開始還在想說為什麼 dart lint 一直噴出警示:
https://ithelp.ithome.com.tw/upload/images/20200125/20106412ZMeLG4gXWh.png

給其他一樣是菜鳥的讀者建議,
在 switch case 當中,還是要放個 default 時的 return 值。

case ConnectionState.none:
case ConnectionState.active:
case ConnectionState.waiting:
default:
    return Center(child: CircularProgressIndicator());

感謝作者文章,
因為個人學習方式習慣做中學,因此會挑選實作篇重的文章參考。

這系列看到這,長惹不少知識,感謝大大!

Bbsonlin iT邦新手 4 級 ‧ 2020-01-30 10:57:08 檢舉

哈哈 能幫助到你是我的榮幸,感謝你給我的系列文肯定

我要留言

立即登入留言