Flutter入門與實戰(一):我的第一個 Flutter 應用之旅

島上碼農發表於2021-05-15

參考官網的的開始使用,配置好開發環境即可進行 Flutter 開發了,當然開發前還是有必要了解一下 Dart 這門語言的,接下來涉及到與其他開發語言不太相同的地方會在文章裡提出來。本教程使用的 flutter 版本為穩定版本 v2.0.6。

建立Flutter 工程

推薦使用命令列的方式新建工程(使用 IDE 建立的過程會比較慢),命令如下:

flutter create hello_world
複製程式碼

Flutter 會預設建立一個示例工程,然後使用命令 開啟工程(code 命令是 vscode 的一個別名,需要在.zshrc配置別名:alias code='/Applications/Visual\ Studio\ Code.app/Contents/Resources/app/bin/code'

code hello_word
複製程式碼

專案目錄結構如下圖所示: image.png 各個目錄或檔案說明如下:

  • android:安卓原生工程配置相關檔案,包括應用圖示,原生資源,許可權配置等,可以參考之前的關於安卓打包釋出的文章:Flutter 如何釋出安卓應用?
  • ios:iOS 原生工程配置相關檔案,熟悉 iOS 開發的會知道具體的用途,其中 最主要的是 Runner 下,設定到原生的配置,如最關鍵的 InfoPlist 檔案,以及許可權相關的配置,這些配置建議在 Xcode 中配置會更為直觀。
  • build:打包輸出檔案,主要是安卓打包檔案,iOS 打包需要通過 Xcode 完成。
  • lib:最重要的目錄,所有原始碼都在這個目錄,其中 main.dart 是入口檔案,而 main 方法是入口方法。
  • test:測試相關檔案
  • web:Flutter 2.0引入的,支援三端統一的 web 端檔案
  • pubspec.yaml:這個檔案十分重要,所有的第三方依賴,以及檔案依賴都通過這個檔案管理,類似與蘋果的 podfile 和安卓的 gradle 檔案。

執行應用

如果要在安卓模擬器執行,則需要安裝安卓 Studio,並配置好模擬器,至於安卓真機除錯與安卓應用開發類似。蘋果也一樣,需要安裝 Xcode並啟動模擬器。真機除錯蘋果相對比較麻煩,需要有開發者賬號,將真機的 identifier(裝置唯一識別符號)加入到對應應用的開發裝置中,這個可以自行百度搜尋如何配置。

完成配置後,選擇要執行的裝置或模擬器(右下角會顯示當前選定的裝置,如果沒選則是 No Device,如下圖),命令列執行 flutter run皆可完成編譯和進入程式碼除錯。 image.png Flutter 應用在除錯過程中是支援熱過載的(pub依賴改變了需要重新編譯),因此儘量使用熱過載,畢竟編譯一次時間停長的。

開發裝置配置

如果是要執行模擬器,對開發的裝置要求還是挺高的,推薦使用 Mac Pro(16GB 記憶體)進行開發。Windows 電腦的話至少也需要16GB 記憶體,模擬器一旦執行起來那“呼呼”的風扇聲讓人聽了感覺電腦幹活挺累的!

來點小修改

執行起來 demo 了,不動手改改程式碼過過癮都沒什麼太大感覺,我們來實現在螢幕中間顯示 Logo,點選後切換圖片的簡單修改。

使用圖片資源需要兩個步驟,第一建立一個圖片資料夾存放圖片資源,第二是需要在 pubspec檔案中指定依賴的資源目錄。新建一個 images 資料夾存放圖片檔案,將圖片檔案(avatar.jpg 和qrcode.jpg)放到images 目錄下。在 pubspec.yaml 檔案中設定 assets 屬性:

	flutter:

		uses-material-design: true
		assets:
    	- images/avatar.jpg
    	- images/qrcode.jpg
    
    # 其他配置
複製程式碼

注意放置的位置不要弄錯了,在 pubspec.yaml 中有相應的註釋。配置完成後需要執行 flutter pub get命令更新一下依賴的資源。

主要程式碼如下所示:

class _MyHomePageState extends State<MyHomePage> {
  List _imageNames = [
    {'image': 'images/avatar.jpg', 'text': '島上碼農'},
    {'image': 'images/qrcode.jpg', 'text': '掃碼關注'}
  ];
  int _index = 0;

  void _onSiwtch() {
    setState(() {
      _index = (++_index) % _imageNames.length;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Container(
          width: 300,
          height: 300,
          child: Column(
            children: [
              Container(
                width: 128,
                height: 128,
                margin: EdgeInsets.only(top: 10, bottom: 10),
                child: Image.asset(
                  _imageNames[_index]['image'],
                  fit: BoxFit.cover,
                ),
              ),
              Text(
                _imageNames[_index]['text'],
              ),
            ],
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _onSiwtch,
        tooltip: '切換',
        child: Icon(Icons.swap_horizontal_circle_outlined),
      ), 
    );
  }
}
複製程式碼

程式碼邏輯如下: _MyHomePageState類是 MyHomePage 的 一個有狀態元件,Flutter 的元件和 React 的類似,分為無狀態和有狀態,無狀態元件無法進行資料更新,有狀態元件有自己的資料狀態,根據資料狀態更新介面。

下劃線_代表這個類、方法或成員變數是私有的,在類的外部無法訪問。在_MyHomePageState 中定義了一個 Map <String, String>型別的陣列(List)_imageNames 以及一個狀態變數陣列控制下標_index。當切換按鈕點選時,會在_onSwitch 方法中通過 setState更改狀態變數_index 的值,從而引起介面的自動重新整理。

頁面元件的元素和層級如下:

  • appBar:導航欄
  • body:主介面
    • Center:居中元件
      • Container:頁面元素容器,類似 html 的 div,通過這個 Container 指定介面中的尺寸和邊距
        • Column:縱向佈局,即元素按縱向一次排布。
          • 圖片容器:用於限定圖片的顯示大小,邊距等
            • 圖片:使用本地資源展示圖片
          • 文字:顯示圖片底下的文字
  • floatingActionButton:懸浮按鈕

可以看到整個頁面的層次和 HTML 很像,實際上 Dart 最開始的設計就是想替換 Javascript 的,而 Flutter 本身很多理念仿照了 React。從程式碼也可以看到,介面的巢狀層級很多,這被很多人吐槽,實際只要我們將元件抽離,就可以有效減少巢狀層級(介面的寫法也有點類似 JSX,只是Flutter 內建了很多佈局元件,簡化了開發)。

最終效果

helloworld.jpg 點選切換按鈕圖片和文字會隨之變化

相關文章