flutter專欄--深入剖析你的第一個flutter應用

使用fvm管理flutter版本

如果你有使用多版本flutter的需求,那么fvm將會給你提供較大的幫助。下面我列舉一下mac + flutter3.35.2的版本的操作命令,完成之后,你將可以隨意切換flutter版本

# 下載fvm相關的依賴
brew tap leoafarias/fvm
brew install fvm# 檢查版本號
fvm --version
# 3.2.1# 下載flutter, 并使用
fvm install 3.35.2 #或者直接下載具體版本號也行
fvm use 3.35.2# 檢查flutter版本號
fvm flutter --version
# 3.35.2

這里由于筆者已經全局安裝一個公司私域的flutter, 并且配置了全局的path, fvm目前識別不到已經安裝的flutter,由于不想影響已經安裝的全局私域flutter,這里可以在flutter命令前直接加fvm,即可使用到fvm安裝的官方flutter,如果不是我這種特殊情況的話,直接使用flutter命令理論是可以切到fvm設置的global源的。

創建你的第一flutter應用

前置步驟

創建flutter之前,你需要配置你的開發環境。具體的步驟官網做了較為詳細的概括,這里將不再贅述,主要分為幾個步驟。

  1. 下載flutter sdk, vscode配置flutter相關插件
  2. 下載配置android studio,下載jdk
  3. 下載配置xcode
  4. 測試手機開啟授權

創建flutter應用

fvm flutter create test_app
cd test_app
fvm flutter run

選擇瀏覽器打開,第一個flutter demo就創建完成了

在這里插入圖片描述

源代碼剖析

結構列表總結

在test_app這個根目錄下,大約有十幾個子目錄,如下。

名稱類型主要作用
test_app目錄項目根目錄
.dart_tool目錄Dart 工具鏈配置與緩存
.idea目錄IDE 配置
android目錄Android 平臺原生代碼
build目錄構建產物(可刪除)
ios目錄iOS 平臺原生代碼
lib目錄核心 Dart 應用代碼
linux目錄Linux 桌面端原生代碼
macos目錄macOS 桌面端原生代碼
test目錄測試代碼
web目錄Web 平臺代碼
windows目錄Windows 桌面端原生代碼
.gitignore文件Git 忽略規則
.metadata文件Flutter 工具元數據
analysis_options.yaml文件靜態代碼分析規則配置
pubspec.lock文件依賴包精確版本鎖定
pubspec.yaml文件項目依賴與元數據配置(非常重要)
README.md文件項目說明文檔
test_app.iml文件IntelliJ 模塊配置

作為入門,我們可以重點關注pubspec.yaml、web、和lib

pubspec.yaml目錄

去除了多余的代碼之后,整體的結果如下

name: test_app
description: "A new Flutter project."
publish_to: 'none'
version: 1.0.0+1environment:sdk: ^3.9.0dependencies:flutter:sdk: fluttercupertino_icons: ^1.0.8dev_dependencies:flutter_test:sdk: flutterflutter_lints: ^5.0.0flutter:uses-material-design: true
name字段

表示當前flutter應用的包名,是一個最基本的字段

我們在導入其他文件時,就需要使用如下方式,如果包名發生變化的話,相應的路徑也需要發生變化

import 'package:flutter_demo/listview_demo/listview_demo.dart';
publish_to

此屬性意為包發布到哪里去

  • none:表示此包不發布;
  • 也可以指定發布的服務器,如果刪除此項配置,那么默認發布到pub.dev
version

此屬性表示當前工程的版本,分為應用程序的版本內部版本號,格式為x.x.x+x,比如1.0.0+1,稱為語義版本號

  • +號前面的叫做version number
  • +號后面的叫做build number

在test_app/android/app/build.gradle.kts這個文件里可以看到安卓打包定版本的具體邏輯

environment

可以配置FlutterDart版本

dependencies
dependencies:flutter:sdk: fluttercupertino_icons: ^1.0.8

添加我們用到的第三方的sdk

  • sdk: flutter意為默認獲取flutter的最新版本,也就是我們機器上的flutter版本,我們也可以在此處添加version來指定flutter的版本;
  • cupertino_icons:給應用程序添加Cupertino圖標的,一般用于iOS;

其實這個本質上跟js項目的生產依賴是一樣的

dev_dependencies

開發依賴,只有運行時才會用到

flutter

Flutter相關的配置

# 確保我們的應用程序中包含Material Icons字體,以使我們能夠使用material Icons類中的圖標;
uses-material-design: true

我們當資源的配置也是在這個配置下進行設置:

  • assets:配置圖片;
  • fonts:配置字體;
  • plugin:該配置只存在于插件項目中,用來配置適配的平臺,一般不要修改;如需添加新平臺,直接添加即可;
web目錄

在這里插入圖片描述

主要包含了一些生成web頁面的靜態資源和模版信息

lib目錄

flutter項目的源代碼

在這里插入圖片描述

main.dart整個應用的入口文件

完整的代碼信息如下

import 'package:flutter/material.dart';void main() {runApp(const MyApp());
}class MyApp extends StatelessWidget {const MyApp({super.key});@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),),home: const MyHomePage(title: 'Flutter Demo Home Page'),);}
}class MyHomePage extends StatefulWidget {const MyHomePage({super.key, required this.title});final String title;@overrideState<MyHomePage> createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage> {int _counter = 0;void _incrementCounter() {setState(() {_counter++;});}@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(backgroundColor: Theme.of(context).colorScheme.inversePrimary,title: Text(widget.title),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[const Text('You have pushed the button this many times:'),Text('$_counter',style: Theme.of(context).textTheme.headlineMedium,),],),),floatingActionButton: FloatingActionButton(onPressed: _incrementCounter,tooltip: 'Increment',child: const Icon(Icons.add),),);}
}
導入依賴
import 'package:flutter/material.dart';

導入了 Material UI 組件庫。Material(opens new window)是一種標準的移動端和web端的視覺設計語言, Flutter 默認提供了一套豐富的 Material 風格的UI組件。

應用入口
void main() {runApp(const MyApp());
}

Flutter 應用中 main 函數為應用程序的入口。main 函數中調用了runApp 方法,它的功能是啟動Flutter應用。runApp它接受一個 Widget參數,在本示例中它是一個MyApp對象,MyApp()是 Flutter 應用的根組件。

也可以簡寫成單行函數

void main() => runApp(MyApp());
應用代碼結構
class MyApp extends StatelessWidget {const MyApp({super.key});@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),),home: const MyHomePage(title: 'Flutter Demo Home Page'),);}
}
  • MyApp類代表 Flutter 應用,它繼承了 StatelessWidget類,這也就意味著應用本身也是一個widget。
  • 在 Flutter 中,大多數東西都是 widget,包括對齊(Align)、填充(Padding)、手勢處理(GestureDetector)等,它們都是以 widget 的形式提供。
  • Flutter 在構建頁面時,會調用組件的build方法,widget 的主要工作是提供一個 build() 方法來描述如何構建 UI 界面(通常是通過組合、拼裝其他基礎 widget )。
  • MaterialApp 是Material 庫中提供的 Flutter APP 框架,通過它可以設置應用的名稱、主題、語言、首頁及路由列表等。MaterialApp也是一個 widget。
  • home 為 Flutter 應用的首頁,它也是一個 widget。
具體代碼解析
MyHomePage
class MyHomePage extends StatefulWidget {const MyHomePage({super.key, required this.title});final String title;// 重寫createState方法,創建與這個Widget關聯的狀態類@overrideState<MyHomePage> createState() => _MyHomePageState();
}class _MyHomePageState extends State<MyHomePage> {// ...
}

MyHomePage 是應用的首頁,它繼承自StatefulWidget類,表示它是一個有狀態的組件(Stateful widget)。

  1. Stateful widget 可以擁有狀態,這些狀態在 widget 生命周期中是可以變的,而 Stateless widget 是不可變的。
  2. Stateful widget 至少由兩個類組成:
    • 一個StatefulWidget類。
    • 一個 State類; StatefulWidget類本身是不變的,但是State類中持有的狀態在 widget 生命周期中可能會發生變化。
    • _MyHomePageState類是MyHomePage類對應的狀態類。這里可以看到,和MyApp 類不同, MyHomePage類中并沒有build方法,取而代之的是,build方法被挪到了_MyHomePageState方法中,至于為什么,后面會進行解讀
const MyHomePage({super.key, required this.title});

構造函數,用于初始化一個名為 MyHomePage 的頁面(Widget)。

State類

_MyHomePageState在就是一個state類,在MyHomePage里面被createState出來,里面主要有兩部分內容, 一是定義了一個計數器狀態,再定義一個狀態自增函數,當按鈕點擊時,會調用此函數,該函數的作用是先自增_counter,然后調用setState 方法。setState方法的作用是通知 Flutter 框架,有狀態發生了改變,Flutter 框架收到通知后,會執行 build 方法來根據新的狀態重新構建界面, Flutter 對此方法做了優化,使重新執行變的很快,所以你可以重新構建任何需要更新的東西,而無需分別去修改各個 widget。

  int _counter = 0;void _incrementCounter() {setState(() {_counter++;});}

二是定一個build函數,用于構建UI頁面

  @overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(backgroundColor: Theme.of(context).colorScheme.inversePrimary,title: Text(widget.title),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[const Text('You have pushed the button this many times:'),Text('$_counter',style: Theme.of(context).textTheme.headlineMedium,),],),),floatingActionButton: FloatingActionButton(onPressed: _incrementCounter,tooltip: 'Increment',child: const Icon(Icons.add),),);}

MyHomePage第一次創建時,_MyHomePageState類會被創建,當初始化完成后,Flutter框架會調用 widget 的build方法來構建 widget 樹,最終將 widget 樹渲染到設備屏幕上。具體解讀如下:

  • Scaffold 是 Material 庫中提供的頁面腳手架,它提供了默認的導航欄、標題和包含主屏幕 widget 樹(后同“組件樹”或“部件樹”)的body屬性,組件樹可以很復雜。本書后面示例中,路由默認都是通過Scaffold創建。
  • body的組件樹中包含了一個Center 組件,Center 可以將其子組件樹對齊到屏幕中心。此例中, Center 子組件是一個Column 組件,Column的作用是將其所有子組件沿屏幕垂直方向依次排列; 此例中Column子組件是兩個 Text,第一個Text 顯示固定文本 “You have pushed the button this many times:”,第二個Text 顯示_counter狀態的數值。
  • floatingActionButton是頁面右下角的帶“+”的懸浮按鈕,它的onPressed屬性接受一個回調函數,代表它被點擊后的處理器,本例中直接將_incrementCounter方法作為其處理函數。

完整流程如下:

當右下角的floatingActionButton按鈕被點擊之后,會調用_incrementCounter方法。在_incrementCounter方法中,首先會自增_counter計數器(狀態),然后setState會通知 Flutter 框架狀態發生變化,接著,Flutter 框架會調用build方法以新的狀態重新構建UI,最終顯示在設備屏幕上。

為什么把build放在State類中
1.方便狀態訪問

如果我們的StatefulWidget有很多狀態,而每次狀態改變都要調用build方法,由于狀態是保存在 State 中的,如果build方法在StatefulWidget中,那么build方法和狀態分別在兩個類中,那么構建時讀取狀態將會很不方便。如果真的將build方法放在 StatefulWidget 中的話,由于構建用戶界面過程需要依賴 State,所以build方法將必須加一個State參數,大概是下面這樣:

Widget build(BuildContext context, State state){//state.counter...}

這樣的話就只能將State的所有狀態聲明為公開的狀態,這樣才能在State類外部訪問狀態!但是,將狀態設置為公開后,狀態將不再具有私密性,這就會導致對狀態的修改將會變的不可控。但如果將build()方法放在State中的話,構建過程不僅可以直接訪問狀態,而且也無需公開私有狀態,這會非常方便。

2.方便繼承StatefulWidget

例如,Flutter 中有一個動畫 widget 的基類AnimatedWidget,它繼承自StatefulWidget類。AnimatedWidget中引入了一個抽象方法build(BuildContext context),繼承自AnimatedWidget的動畫 widget 都要實現這個build方法。現在設想一下,如果StatefulWidget 類中已經有了一個build方法,正如上面所述,此時build方法需要接收一個 State 對象,這就意味著AnimatedWidget必須將自己的 State 對象(記為_animatedWidgetState)提供給其子類,因為子類需要在其build方法中調用父類的build方法

class MyAnimationWidget extends AnimatedWidget{@overrideWidget build(BuildContext context, State state){//由于子類要用到AnimatedWidget的狀態對象_animatedWidgetState,//所以AnimatedWidget必須通過某種方式將其狀態對象_animatedWidgetState//暴露給其子類   super.build(context, _animatedWidgetState)}
}

這樣很顯然是不合理的,因為

  • AnimatedWidget的狀態對象是AnimatedWidget內部實現細節,不應該暴露給外部。
  • 如果要將父類狀態暴露給子類,那么必須得有一種傳遞機制,而做這一套傳遞機制是無意義的,因為父子類之間狀態的傳遞和子類本身邏輯是無關的。
總結來說
  • build 方法需要根據可變狀態(如 _counter 來構建用戶界面。這些可變狀態保存在 State 子類(如 _MyHomePageState)中。將 build 方法放在 State 子類里,可以直接訪問(通過context)這些狀態(例如 _counter),無需通過復雜的傳遞機制或將狀態設置為公開,從而破壞了狀態的封裝性。
  • StatefulWidget對外的,負責接收不可變的配置數據。
  • State對內的,負責管理可變的狀態。

參考

《Flutter實戰·第二版》

https://juejin.cn/post/7033933629403168799

4.拓展閱讀

flutter專欄–移動開發技術的發展與flutter的概要

flutter專欄–dart基礎知識

關注我,有空一起閑聊

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/95284.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/95284.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/95284.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MongoDB 聚合查詢超時:索引優化與分片策略的踩坑記錄

人們眼中的天才之所以卓越非凡&#xff0c;并非天資超人一等而是付出了持續不斷的努力。1萬小時的錘煉是任何人從平凡變成超凡的必要條件。———— 馬爾科姆格拉德威爾 &#x1f31f; Hello&#xff0c;我是Xxtaoaooo&#xff01; &#x1f308; “代碼是邏輯的詩篇&#xff…

Augmentcode免費額度AI開發WordPress商城實戰

Augment AI開發WordPress商城實戰&#xff1a;從零構建到免費額度續杯完整指南 前言 在AI編程工具日益普及的今天&#xff0c;如何高效利用這些工具來開發實際項目成為了開發者關注的焦點。本文將詳細介紹如何使用Augment AI從零開始構建一個功能完整的WordPress商城系統&#…

【C++八股文】數據結構篇

一、單例模式優化實現 原代碼問題分析 ?內存序重排序風險?&#xff1a;雙重檢查鎖在C中可能因指令重排導致半初始化對象被訪問?鎖粒度過大?&#xff1a;每次獲取實例都需要加鎖&#xff0c;影響性能?線程安全性不足?&#xff1a;未考慮C11前的內存模型問題 改進方案&a…

并發編程——15 線程池ForkJoinPool實戰及其工作原理分析

1 一道算法題引發的思考及其實現 1.1 算法題 問&#xff1a;如何充分利用多核 CPU 的性能&#xff0c;快速對一個2千萬大小的數組進行排序&#xff1f; 這道題可以通過歸并排序來解決&#xff1b; 1.2 什么是歸并排序&#xff1f; 歸并排序&#xff08;Merge Sort&#xff…

Kafka面試精講 Day 6:Kafka日志存儲結構與索引機制

【Kafka面試精講 Day 6】Kafka日志存儲結構與索引機制 在“Kafka面試精講”系列的第6天&#xff0c;我們將深入剖析 Kafka的日志存儲結構與索引機制。這是Kafka高性能、高吞吐量背后的核心設計之一&#xff0c;也是中高級面試中的高頻考點。面試官常通過這個問題考察候選人是否…

Linux 字符設備驅動框架學習記錄(三)

Linux字符設備驅動開發新框架詳解 一、新舊驅動框架對比 傳統字符設備驅動流程 手動分配設備號 (register_chrdev_region)實現file_operations結構體使用mknod手動創建設備節點 新式驅動框架優勢 自動設備號分配&#xff1a;動態申請避免沖突自動節點創建&#xff1a;通過class…

《計算機網絡安全》實驗報告一 現代網絡安全挑戰 拒絕服務與分布式拒絕服務攻擊的演變與防御策略(1)

目 錄 摘 要 一、研究背景與目的 1.1 介紹拒絕服務&#xff08;DoS&#xff09;和分布式拒絕服務&#xff08;DDoS&#xff09;攻擊的背景 &#xff08;1&#xff09;拒絕服務攻擊&#xff08;DoS&#xff09;  &#xff08;2&#xff09;分布式拒絕服務攻擊&#xff0…

深度學習篇---模型組成部分

模型組成部分&#xff1a;在 PyTorch 框架下進行圖像分類任務時&#xff0c;深度學習代碼通常由幾個核心部分組成。這些部分中有些可以在不同網絡間復用&#xff0c;有些則需要根據具體任務或網絡結構進行修改。下面我將用通俗易懂的方式介紹這些組成部分&#xff1a;1. 數據準…

關于ANDROUD APPIUM安裝細則

1&#xff0c;可以先參考一下連接 PythonAppium自動化完整教程_appium python教程-CSDN博客 2&#xff0c;appium 需要對應的版本的node&#xff0c;可以用nvm對node 進行版本隔離 3&#xff0c;對應需要安裝android stuido 和對應的sdk &#xff0c;按照以上連接進行下載安…

八、算法設計與分析

1 算法設計與分析的基本概念 1.1 算法 定義 &#xff1a;算法是對特定問題求解步驟的一種描述&#xff0c;是有限指令序列&#xff0c;每條指令表示一個或多個操作。特性 &#xff1a; 有窮性&#xff1a;算法需在有限步驟和時間內結束。確定性&#xff1a;指令無歧義&#xff…

機器學習從入門到精通 - 神經網絡入門:從感知機到反向傳播數學揭秘

機器學習從入門到精通 - 神經網絡入門&#xff1a;從感知機到反向傳播數學揭秘開場白&#xff1a;點燃你的好奇心 各位&#xff0c;有沒有覺得那些能識圖、懂人話、下棋碾壓人類的AI特別酷&#xff1f;它們的"大腦"核心&#xff0c;很多時候就是神經網絡&#xff01;…

神經網絡模型介紹

如果你用過人臉識別解鎖手機、刷到過精準推送的短視頻&#xff0c;或是體驗過 AI 聊天機器人&#xff0c;那么你已經在和神經網絡打交道了。作為深度學習的核心技術&#xff0c;神經網絡模仿人腦的信息處理方式&#xff0c;讓機器擁有了 “學習” 的能力。一、什么是神經網絡&a…

蘋果開發中什么是Storyboard?object-c 和swiftui 以及Storyboard到底有什么關系以及邏輯?優雅草卓伊凡

蘋果開發中什么是Storyboard&#xff1f;object-c 和swiftui 以及Storyboard到底有什么關系以及邏輯&#xff1f;優雅草卓伊凡引言由于最近有個客戶咨詢關于 蘋果內購 in-purchase 的問題做了付費咨詢處理&#xff0c;得到問題&#xff1a;“昨天試著把您的那幾部分code 組裝成…

孩子玩手機都近視了,怎樣限制小孩的手機使用時長?

最近兩周&#xff0c;我給孩子檢查作業時發現娃總是把眼睛瞇成一條縫&#xff0c;而且每隔幾分鐘就會用手背揉眼睛&#xff0c;有時候揉得眼圈都紅了。有一次默寫單詞&#xff0c;他把 “太陽” 寫成了 “大陽”&#xff0c;我給他指出來&#xff0c;他卻盯著本子說 “沒有錯”…

醫療AI時代的生物醫學Go編程:高性能計算與精準醫療的案例分析(六)

第五章 案例三:GoEHRStream - 實時電子病歷數據流處理系統 5.1 案例背景與需求分析 5.1.1 電子病歷數據流處理概述 電子健康記錄(Electronic Health Record, EHR)系統是現代醫療信息化的核心,存儲了患者從出生到死亡的完整健康信息,包括 demographics、診斷、用藥、手術、…

GEM5學習(2):運行x86Demo示例

創建腳本 配置腳本內容參考官網的說明gem5: Creating a simple configuration script 首先根據官方說明創建腳本文件 mkdir configs/tutorial/part1/ touch configs/tutorial/part1/simple.py simple.py 中的內容如下&#xff1a; from gem5.prebuilt.demo.x86_demo_board…

通過 FinalShell 訪問服務器并運行 GUI 程序,提示 “Cannot connect to X server“ 的解決方法

FinalShell 是一個 SSH 客戶端&#xff0c;默認情況下 不支持 X11 圖形轉發&#xff08;不像 ssh -X 或 ssh -Y&#xff09;&#xff0c;所以直接運行 GUI 程序&#xff08;如 Qt、GNOME、Matplotlib 等&#xff09;會報錯&#xff1a; Error: Cant open display: Failed to c…

1.人工智能——概述

應用領域 替代低端勞動&#xff0c;解決危險、高體力精力損耗領域 什么是智能制造&#xff1f;數字孿生&#xff1f;邊緣計算&#xff1f; 邊緣計算 是 數字孿生 的 “感官和神經末梢”&#xff0c;負責采集本地實時數據和即時反應。瑣碎數據不上傳總服務器&#xff0c;實時進行…

傳統園區能源轉型破局之道:智慧能源管理系統驅動的“源-網-荷-儲”協同賦能

傳統園區能源結構轉型 政策要求&#xff1a;福建提出2025年可再生能源滲透率≥25%&#xff0c;山東強調“源網荷儲一體化”&#xff0c;安徽要求清潔能源就地消納。系統解決方案&#xff1a;多能協同調控&#xff1a;集成光伏、儲能、充電樁數據&#xff0c;通過AI算法動態優化…

[光學原理與應用-353]:ZEMAX - 設置 - 可視化工具:2D視圖、3D視圖、實體模型三者的區別,以及如何設置光線的數量

在光學設計軟件ZEMAX中&#xff0c;2D視圖、3D視圖和實體模型是三種不同的可視化工具&#xff0c;分別用于從不同維度展示光學系統的結構、布局和物理特性。它們的核心區別體現在維度、功能、應用場景及信息呈現方式上&#xff0c;以下是詳細對比&#xff1a;一、維度與信息呈現…