從 flutter demo走進flutter 世界

行雲流水發表於2021-03-11

工程結構

開啟Android studio 建立一個flutter 專案,會預設建立一個計數器專案。在右邊project 下,可以看到:

image.png 分析一下幾個重要的檔案目錄和檔案:

android:包含Android的特定檔案和Android子工程
build:Android 和iOS 的構建產物
ios:包含iOS 的特定檔案和iOS 子工程
lib:放置flutter 程式碼
    main.dart:程式的入口檔案,類似Android 的application
test:測試檔案
flutter_app.iml:工程配置檔案
pubspec.lock:記錄當前專案實際依賴資訊的檔案
pubspec.yaml:管理第三方庫和資原始檔

複製程式碼

之所以有Android 和iOS 子專案,是因為flutter 最終會以原生的形式執行。

從簡單的demo學習flutter專案的執行機制

在flutter 的世界中,一切都是widget,widget 是元件視覺效果的封裝,是 UI 介面的載體,通過 build方法來構建UI頁面。 看看main.dart 檔案中的程式碼

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}
複製程式碼
  1. 從main函式開始,呼叫 runApp方法 傳入MyApp(就是一個widget),APP就是我們看到的首頁。
  2. 在 MyApp的build 方法中,返回了 MaterialApp(也是一個widget),裡面還有很多可配置的屬性,比如應用主題、應用名稱、語言識別符號、元件路由等。
  3. 在 MaterialApp,看到 MyHomePage(也是一個widget),但是這個 StatefulWidget 的子類,構建UI不是直接通過build 方法,而是交給 _MyHomePageState來完成。

到這來就可以看到,在flutter 中有兩種 widget,StatelessWidget 和 StatefulWidget。

StatelessWidget:無狀態的widget,UI構建的從一開始就是確定的,在 widget 的生命週期中不會發生變化。

StatefulWidget:有狀態的widget,在widget 的生命週期中資料發生變化,在資料發生變化後,呼叫 setState方法來通知flutter 框架,重新建立widget。

隨著資料的變化重新建立和銷燬widget,會不會對效能有影響呢,flutter 如何優化的?

答案是:不會。因為框架內部會通過一箇中間層去收斂上層 UI 配置對底層真實渲染的改動,從而最大程度降低對真實渲染檢視的修改,提高渲染效率,而不是上層 UI 配置變了就需要銷燬整個渲染檢視樹重建。

總結

從上面可以看出,在flutter 的世界裡,widget 是無處不在,在頁面上看到的一切的一切都是widget,如:AppBar、Center、Text、FloatingActionButton……都是widget,我們可以在widget構建的時候,做好配置,如,Text 文字大小、文字顏色、文字內容、點選事件等等,然後在資料發生變化後,通過呼叫 setState方法,就可以更新UI了。

相關文章