我的第一個Flutter 應用Demo Aireport

ZacJi發表於2018-05-29

我的第一個Flutter 應用Demo Aireport
在大略看完了Flutter的官方文件後, 我開始嘗試做一個完整的應用Demo. 抱著初次開發不要給自己挖坑的前提, 我選擇了一個簡單而實用的空氣質量專案: Aireport. 這是我之前自己開發的一個iOS原生App, 因為是給自己用, 因此專案很簡單, 幾百行程式碼. 同時做一款Flutter版的Aireport也能夠探尋兩者具體的差異點.
UI

首先說一下Flutter應用的開發流程.

第一步自然是新建工程.根據我的《閉坑指南》,編輯器還是強烈建議使用Google自家的Android Studio, 無論是外掛支援程度還是速度上都要好上不少(和VS Code相比).

然後是引入第三方庫.這裡我使用了最基本的幾個庫, 包含有圖示庫、網路庫、json轉model以及本地儲存.

cupertino_icons
http
json_annotation
shared_preferences
複製程式碼

Flutter目前還沒有提供一個非常好的json轉model的方案, json_annotation是官方目前推薦的“最方便”的model庫, 但還是需要通過指令碼的方式生成json轉model類. 這顯然沒有動態轉換但效率高.

我在網路層和UI層之間做了一個簡單的儲存層, 用於快取網路請求的資料.

接下來就是正式開始編寫程式碼咯. 作為一個略懂前端的iOS開發者, Dart本身的語法上手速度還是很快的, 不過這個層層巢狀的結構實在是太噁心了, Android Studio自帶的程式碼格式化似似乎也不太穩定.

其次是Flutter的佈局. 大體的佈局和前端佈局框架很相像, 但它將功能“過分元件化”了, 原本DIV都有都Padding、Center、Align屬性全部Widget化, 因此如果你的佈局比較複雜, 很可能需要多個佈局Widget巢狀來實現.

看到這樣的程式碼我的內心是崩潰的
看到這樣的程式碼我的內心是崩潰的?

如果你是原生開發者, 你會很自然的認為TableView(ListView)、CollectionView(GridView)是一個UI控制元件,包含了對Cell的展示、控制、點選事件的處理. 而Flutter將這個控制元件拆分成了多個元件,ListView和GridView僅僅承擔佈局的工作, 點選事件等需要通過別的控制元件來實現.

可以這樣理解, Flutter儘可能的將UI、佈局、功能進行分解Widget化, 我還不確定這樣做的目的是出於效能優化的考慮還是別的原因. 當然適當的元件化是好的, 能夠使控制元件足夠靈活, 也能對效能有適當提升. 但如此小顆粒度的分解目前看來也帶來了一些使用上的問題, 包括上面提到的多層巢狀.

當你的程式碼寫的差不多的時候, 就要開始除錯程式碼. 除錯Flutter的過程是愉悅的, 任何更改後按下儲存快捷鍵你就能立刻看到修改後的樣子(理想情況下).令人欣慰的是Android Studio還提供了足夠強大的除錯工具來幫助我們進行糾錯, 在這點上VS Code能做的就很少了, 至少目前來說.

如果需要對UI進行除錯, 可以嘗試加入

import 'package:flutter/rendering.dart';
debugPaintSizeEnabled= true;
複製程式碼

我的第一個Flutter 應用Demo Aireport
通過輔助線我們可以快速定位控制元件的佈局
我的第一個Flutter 應用Demo Aireport
Android Studio還提供了inspector檢視, 包含了Widget樹狀圖以及了Widget的各種屬性, 類似於瀏覽器的偵錯程式. 不過目前的檢視還比較混亂, 應該是把底層的所有Widget無差別展示出來, 對於感興趣底層實現的同學可以研究一下.

專案開發完成, 接下來就是打包釋出了. Flutter有兩種執行方式, debug模式提供了熱更新等功能方便我們快速開發, 但執行效率低下. 而release模式剔除了無用的功能並以AOT方式執行, 效率更高.

flutter build ios
複製程式碼

構建release的iOS版本, 然後去Xcode中設定app的Icon、啟動頁、版本號、證書等等, 就如同一般的原生應用一樣. 注意, 如果你的app中使用了非HTTPS協議還是需要在Plist中對安全規則進行修改, 地理位置、相機許可權也是同理.

至此, 我的Flutter iOS專案已經開發完成了. App Store2天左右就通過了稽核, 顯然目前Apple對於Flutter的態度還是和善的, 但未來的政策還是未知.

在開發這個專案的過程中, 我遇到了幾個問題, 也想跟大家分享一下.

首先是佈局.

我的第一個Flutter 應用Demo Aireport
這個頁面其實相當簡單, 上面是一個搜尋框, 下面是一個ListView. 但我始終無法通過簡單的佈局實現這個效果. 一開始我本能但使用Column來放置兩個控制元件, 但報錯, 提示的大意是不能在一個可以滾動的元件內部套另一個可以滾動的元件, 因為無法確定子元件的高度. Column的佈局其實類似iOS中的ScrollerView, 他的內部填充高度是無限的, 和螢幕高度無關. 可以給ListView新增高度解決問題, 但我又無法計算當前ListView的具體高度(方法是有, 但我覺得太複雜了, 還要區分X這種特殊機型).

最後我使用了Stack, 將搜尋框懸浮在ListView之上, 再給ListView套一個Container設定到上邊距的距離, 最終實現了這個效果. 雖然最終的效果還可以, 但我覺得這樣但佈局明顯還不夠優雅, 閱讀起來難度也很大. 如果有更好但解決辦法請告訴我.

其次是尚有很多系統層級的功能無法實現. 比如StatusBar的顏色, 我希望的是首頁是白色字型, 搜尋頁是黑色字型. 但目前似乎只能設定一種固定的顏色. 嘗試使用SystemChrome強制設定StatusBar的顏色,但跳轉到搜尋頁顏色又會變為黑色, 返回時不能自動變為白色. 嘗試尋找類似於ViewWillAppear這樣的事件無果, 暫時只能通過後一個頁面的回撥來觸發修改顏色的程式碼.

Notification也是一個暫時無法實現的功能.目前官方已經提供了firebase_messaging外掛用於收取推送訊息, 但無法傳送本地推送, 也就無法實現小圓點的功能.當然我們還是可以通過呼叫原生方法實現.

總結一下.

從UI層面, Flutter由於提供了一套脫離特定平臺的自有渲染引擎, 幾乎能夠實現任何你想要達到的效果. 但在這之前你可能需要好好研究一下它的佈局Widget, 然後暫時(可能永遠)忍耐一下多層巢狀的程式碼風格. 當然適當將自己的頁面元件化也是一個好的方法.

邏輯層面, 官方已經推出了數量可觀的基礎庫, 處理基本的事務沒有特別大的問題. 但我們還是希望有大量好用的第三方庫出現, 豐富Flutter的開發生態.

下一篇會做一個iOS原生應用和Flutter的對比評測.

最後放上專案GitHub地址: https://github.com/jihongboo/Aireport_Flutter 現已上架AppStore: https://itunes.apple.com/cn/app/aireport-flutter/id1390259423?mt=8

相關文章