<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                在專欄的第一篇預習文章中,我和你一起搭建了 Flutter 的開發環境,并且通過自帶的 hello\_world 示例,和你演示了 Flutter 項目是如何運行在 Android 和 iOS 模擬器以及真機上的。 今天,我會通過 Android Studio 創建的 Flutter 應用模板,帶你去了解 Flutter 的項目結構,分析 Flutter 工程與原生 Android 和 iOS 工程有哪些聯系,體驗一個有著基本功能的 Flutter 應用是如何運轉的,從而加深你對構建 Flutter 應用的關鍵概念和技術的理解。 如果你現在還不熟悉 Dart 語言也不用擔心,只要能夠理解基本的編程概念(比如,類型、變量、函數和面向對象),并具備一定的前端基礎(比如,了解 View 是什么、頁面基本布局等基礎知識),就可以和我一起完成今天的學習。而關于 Dart 語言基礎概念的講述、案例分析,我會在下一個模塊和你展開。 ## 計數器示例工程分析 首先,我們打開 Android Studio,創建一個 Flutter 工程應用 flutter\_app。Flutter 會根據自帶的應用模板,自動生成一個簡單的計數器示例應用 Demo。我們先運行此示例,效果如下: :-: ![](https://img.kancloud.cn/3a/fe/3afe6b35238d1e57c8ae6bec9be61624_828x1792.png) 圖 1 計數器示例運行效果 每點擊一次右下角帶“+”號的懸浮按鈕,就可以看到屏幕中央的數字隨之 +1。 ### 工程結構 在體會了示例工程的運行效果之后,我們再來看看 Flutter 工程目錄結構,了解 Flutter 工程與原生 Android 和 iOS 工程之間的關系,以及這些關系是如何確保一個 Flutter 程序可以最終運行在 Android 和 iOS 系統上的。 :-: ![](https://img.kancloud.cn/e7/ec/e7ecbd5c21895e396c14154b2f226dfc_1036x374.png) 圖 2 Flutter 工程目錄結構 可以看到,除了 Flutter 本身的代碼、資源、依賴和配置之外,Flutter 工程還包含了 Android 和 iOS 的工程目錄。 這也不難理解,因為 Flutter 雖然是跨平臺開發方案,但卻需要一個容器最終運行到 Android 和 iOS 平臺上,所以**Flutter 工程實際上就是一個同時內嵌了 Android 和 iOS 原生子工程的父工程**:我們在 lib 目錄下進行 Flutter 代碼的開發,而某些特殊場景下的原生功能,則在對應的 Android 和 iOS 工程中提供相應的代碼實現,供對應的 Flutter 代碼引用。 Flutter 會將相關的依賴和構建產物注入這兩個子工程,最終集成到各自的項目中。而我們開發的 Flutter 代碼,最終則會以原生工程的形式運行。 ### 工程代碼 在對 Flutter 的工程結構有了初步印象之后,我們就可以開始學習 Flutter 的項目代碼了。 Flutter 自帶的應用模板,也就是這個計數器示例,對初學者來說是一個極好的入門范例。在這個簡單示例中,從基礎的組件、布局到手勢的監聽,再到狀態的改變,Flutter 最核心的思想在這 60 余行代碼中展現得可謂淋漓盡致。 為了便于你學習理解,領會構建 Flutter 程序的大體思路與關鍵技術,而不是在一開始時就陷入組件的 API 細節中,我刪掉了與核心流程無關的組件配置代碼及布局邏輯,在不影響示例功能的情況下對代碼進行了改寫,并將其分為兩部分: * 第一部分是應用入口、應用結構以及頁面結構,可以幫助你理解構建 Flutter 程序的基本結構和套路; * 第二部分則是頁面布局、交互邏輯及狀態管理,能夠幫你理解 Flutter 頁面是如何構建、如何響應交互,以及如何更新的。 首先,我們來看看**第一部分的代碼**,也就是應用的整體結構: ``` import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) => MaterialApp(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> { Widget build(BuildContext context) => {...}; } ``` 在本例中,Flutter 應用為 MyApp 類的一個實例,而 MyApp 類繼承自 StatelessWidget 類,這也就意味著應用本身也是一個 Widget。事實上,在 Flutter 中,Widget 是整個視圖描述的基礎,在 Flutter 的世界里,包括應用、視圖、視圖控制器、布局等在內的概念,都建立在 Widget 之上,**Flutter 的核心設計思想便是一切皆 Widget**。 Widget 是組件視覺效果的封裝,是 UI 界面的載體,因此我們還需要為它提供一個方法,來告訴 Flutter 框架如何構建 UI 界面,這個方法就是 build。 在 build 方法中,我們通常通過對基礎 Widget 進行相應的 UI 配置,或是組合各類基礎 Widget 的方式進行 UI 的定制化。比如在 MyApp 中,我通過 MaterialApp 這個 Flutter App 框架設置了應用首頁,即 MyHomePage。當然,MaterialApp 也是一個 Widget。 MaterialApp 類是對構建 material 設計風格應用的組件封裝框架,里面還有很多可配置的屬性,比如應用主題、應用名稱、語言標識符、組件路由等。但是,這些配置屬性并不是本次分享的重點,如果你感興趣的話,可以參考 Flutter 官方的[API 文檔](https://api.flutter.dev/flutter/material/MaterialApp/MaterialApp.html),來了解 MaterialApp 框架的其他配置能力。 MyHomePage 是應用的首頁,繼承自 StatefulWidget 類。這,代表著它是一個有狀態的 Widget(Stateful Widget),而 \_MyHomePageState 就是它的狀態。 如果你足夠細心的話就會發現,雖然 MyHomePage 類也是 Widget,但與 MyApp 類不同的是,它并沒有一個 build 方法去返回 Widget,而是多了一個 createState 方法返回 \_MyHomePageState 對象,而 build 方法則包含在這個 \_MyHomePageState 類當中。 那么,**StatefulWidget 與 StatelessWidget 的接口設計,為什么會有這樣的區別呢?** 這是因為 Widget 需要依據數據才能完成構建,而對于 StatefulWidget 來說,其依賴的數據在 Widget 生命周期中可能會頻繁地發生變化。由 State 創建 Widget,以數據驅動視圖更新,而不是直接操作 UI 更新視覺屬性,代碼表達可以更精煉,邏輯也可以更清晰。 在了解了計數器示例程序的整體結構以后,我們再來看看這個**示例代碼的第二部分**,也就是頁面布局及交互邏輯部分。 ``` 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: Text('You have pushed the button this many times:$_counter')), floatingActionButton: FloatingActionButton(onPressed: _incrementCounter) ); } ``` \_MyHomePageState 中創建的 Widget Scaffold,是 Material 庫中提供的頁面布局結構,它包含 AppBar、Body,以及 FloatingActionButton。 * AppBar 是頁面的導航欄,我們直接將 MyHomePage 中的 title 屬性作為標題使用。 * body 則是一個 Text 組件,顯示了一個根據 \_counter 屬性可變的文本:‘You have pushed the button this many times:$\_counter’。 * floatingActionButton,則是頁面右下角的帶“+”的懸浮按鈕。我們將 \_incrementCounter 作為其點擊處理函數。 \_incrementCounter 的實現很簡單,使用 setState 方法去自增狀態屬性 \_counter。setState 方法是 Flutter 以數據驅動視圖更新的關鍵函數,它會通知 Flutter 框架:我這兒有狀態發生了改變,趕緊給我刷新界面吧。而 Flutter 框架收到通知后,會執行 Widget 的 build 方法,根據新的狀態重新構建界面。 **這里需要注意的是:狀態的更改一定要配合使用 setState。**通過這個方法的調用,Flutter 會在底層標記 Widget 的狀態,隨后觸發重建。于我們的示例而言,即使你修改了 \_counter,如果不調用 setState,Flutter 框架也不會感知到狀態的變化,因此界面上也不會有任何改變(你可以動手驗證一下)。 下面的圖 3,就是整個計數器示例的代碼流程示意圖。通過這張圖,你就能夠把這個實例的整個代碼流程串起來了: :-: ![](https://img.kancloud.cn/34/01/3401b99587eafa7c0c1ed446eb936f36_1352x744.png) 圖 3 代碼流程示意圖 MyApp 為 Flutter 應用的運行實例,通過在 main 函數中調用 runApp 函數實現程序的入口。而應用的首頁則為 MyHomePage,一個擁有 \_MyHomePageState 狀態的 StatefulWidget。\_MyHomePageState 通過調用 build 方法,以相應的數據配置完成了包括導航欄、文本及按鈕的頁面視圖的創建。 而當按鈕被點擊之后,其關聯的控件函數 \_incrementCounter 會觸發調用。在這個函數中,通過調用 setState 方法,更新 \_counter 屬性的同時,也會通知 Flutter 框架其狀態發生變化。隨后,Flutter 會重新調用 build 方法,以新的數據配置重新構建 \_MyHomePageState 的 UI,最終完成頁面的重新渲染。 Widget 只是視圖的“配置信息”,是數據的映射,是“只讀”的。對于 StatefulWidget 而言,當數據改變的時候,我們需要重新創建 Widget 去更新界面,這也就意味著 Widget 的創建銷毀會非常頻繁。 為此,Flutter 對這個機制做了優化,其框架內部會通過一個中間層去收斂上層 UI 配置對底層真實渲染的改動,從而最大程度降低對真實渲染視圖的修改,提高渲染效率,而不是上層 UI 配置變了就需要銷毀整個渲染視圖樹重建。 這樣一來,Widget 僅是一個輕量級的數據配置存儲結構,它的重新創建速度非常快,所以我們可以放心地重新構建任何需要更新的視圖,而無需分別修改各個子 Widget 的特定樣式。關于 Widget 具體的渲染過程細節,我會在后續的第 9 篇文章“Widget,構建 Flutter 界面的基石”中向你詳細介紹,在這里就不再展開了。 ## 總結 今天的這次 Flutter 項目初體驗,我們就先進行到這里。接下來,我們一起回顧下涉及到的知識點。 首先,我們通過 Flutter 標準模板創建了計數器示例,并分析了 Flutter 的項目結構,以及 Flutter 工程與原生 Android、iOS 工程的聯系,知道了 Flutter 代碼是怎么運行在原生系統上的。 然后,我帶你學習了示例項目代碼,了解了 Flutter 應用結構及頁面結構,并認識了構建 Flutter 的基礎,也就是 Widget,以及狀態管理機制,知道了 Flutter 頁面是如何構建的,StatelessWidget 與 StatefulWidget 的區別,以及如何通過 State 的成員函數 setState 以數據驅動的方式更新狀態,從而更新頁面。 有原生 Android 和 iOS 框架開發經驗的同學,可能更習慣命令式的 UI 編程風格:手動創建 UI 組件,在需要更改 UI 時調用其方法修改視覺屬性。而 Flutter 采用聲明式 UI 設計,我們只需要描述當前的 UI 狀態(即 State)即可,不同 UI 狀態的視覺變更由 Flutter 在底層完成。 雖然命令式的 UI 編程風格更直觀,但聲明式 UI 編程方式的好處是,可以讓我們把復雜的視圖操作細節交給框架去完成,這樣一來不僅可以提高我們的效率,也可以讓我們專注于整個應用和頁面的結構和功能。 所以在這里,我非常希望你能夠適應這樣的 UI 編程思維方式的轉換。 ## 思考題 最后,我給你留下一個思考題吧。 示例項目代碼在 \_MyHomePageState 類中,直接在 build 函數里以內聯的方式完成了 Scaffold 頁面元素的構建,這樣做的好處是什么呢? 在實現同樣功能的情況下,如果將 Scaffold 頁面元素的構建封裝成一個新 Widget 類,我們該如何處理?
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看