[此處應(yīng)該有一張圖]
本文均依據(jù)于flutter官方文檔流程,只梳理其中的坑點(diǎn)。
使用方法:由于本文可能會(huì)較長,知識(shí)點(diǎn)零散,請讀者善用Ctrl+F。
基于Flutter2.0
Windows+VS Code向
請注意:本文 不是教程內(nèi)容,章節(jié)名與flutter官方文檔對(duì)應(yīng)章節(jié)一致,只用于備查和幫助學(xué)習(xí)中遇到問題的童鞋,歡迎指正。
開始使用Flutter
安裝和環(huán)境配置
系統(tǒng)選擇:Windows
獲取 Flutter SDK
從教程中的鏈接下載最新的stable安裝包,建議解壓到其他盤或者用戶路徑下。然后win+s輸入env添加flutter的bin路徑到環(huán)境變量中。
這里就有一個(gè)問題,修改環(huán)境變量后,需要使用環(huán)境變量的進(jìn)程(如:ternimal,cmd,vscode等)都需要重啟,保證進(jìn)程內(nèi)環(huán)境變量被封信。
知識(shí)點(diǎn):系統(tǒng)環(huán)境變量只會(huì)在啟動(dòng)進(jìn)程時(shí)注入進(jìn)程,由一個(gè)進(jìn)程向啟動(dòng)的另外一個(gè)進(jìn)程注入。
運(yùn)行 flutter doctor
flutter doctor檢查flutter相關(guān)環(huán)境是否可用,按照你的需要來判斷,如果紅叉部分和你要用的無關(guān),那么忽略它就是。如你想要用VS Code做Web開發(fā),你只需要關(guān)注Flutter、瀏覽器和VS Code是不是勾,其他的叉叉對(duì)你沒有任何影響。
檢查結(jié)果里如果Android toolchain是叉叉,你又不想裝Android Studio,那么自己安裝Android SDK和Java就可以了。如果你安裝了VS,那么用VS Installer安裝xmarin相關(guān)的安卓SDK、虛擬機(jī)、JDK等組件就可以搞定。
請注意,F(xiàn)lutter教程中提供的Google USB Driver下載鏈接只是一個(gè)公版驅(qū)動(dòng),很多國產(chǎn)手機(jī)不一定能夠適配,請自行安裝手機(jī)廠商自己提供的驅(qū)動(dòng)。如果廠商沒有提供驅(qū)動(dòng)或者下載安裝之后仍然檢測不到,不用擔(dān)心,在安裝好Android SDK后,在Android SDK管理器里安裝附加程序中Google USB Driver己可。
提示:如果你安裝了Microfost Edge,檢查結(jié)果中Chrome是叉叉也沒關(guān)系,F(xiàn)lutter能夠識(shí)別Edge。
編譯工具設(shè)定
本教程選擇:Visual Studio Code
注意點(diǎn),一定要按照教程安裝插件后重啟VS Code。然后,按快捷鍵 Ctrul + ` 打開終端,鍵入Flutter命令是否能找到。
這里就有一個(gè)問題,VS Code終端可能會(huì)提示Flutter命名無效。原因有以下幾點(diǎn):
- 很多童鞋在前面教程中下載Flutter SDK后解壓放到了高權(quán)限目錄,如C:盤除用戶目錄之外的其他目錄下。這里建議一般放在其他盤或者用戶目錄下。
- VS Code在設(shè)置Flutter的環(huán)境變量前就已經(jīng)啟動(dòng),或者啟動(dòng)VS Code的資源管理器/啟動(dòng)器就已經(jīng)打開。所以,喜歡使用啟動(dòng)器的小伙伴注意了:
如果啟動(dòng)器沒有重啟過,那么它的環(huán)境變量中必然是沒有FlutterSDK的Path的。請使用開始菜單或桌面圖表重啟VS Code,或者重啟啟動(dòng)器再啟動(dòng)VS Code,不必像網(wǎng)上那些教程那樣重啟電腦。
開發(fā)體驗(yàn)初探
這個(gè)環(huán)節(jié)講如何創(chuàng)建應(yīng)用和編譯運(yùn)行應(yīng)用。
注意,即使裝了插件,在VS Code的
Ctrl+Shift+P中也沒有全部命令,只有一些常規(guī)的。
在官方后續(xù)的教程中,可能是因?yàn)榻坛滩皇怯蓡我蝗藛T寫就,同樣的操作可能在不同的地方介紹的方式會(huì)不統(tǒng)一。所以,作為程序員,應(yīng)該學(xué)會(huì)全部使用終端輸入命令的方式。本文都是采用終端命令來講述操作
前提一:要?jiǎng)?chuàng)建Windows桌面應(yīng)用嗎?
官方教程鏈接:Flutter 桌面支持
在Flutter2.0版本中,桌面應(yīng)用還是處于beta版本中,幸運(yùn)的是stable版本包含了一份Beta版本的快照,如果你需要嘗試Windows桌面應(yīng)用,那么你需要在終端中執(zhí)行如下命令:
// 啟動(dòng)windows桌面支持
PS >flutter config --enable-windows-desktop
// 檢查Windows的狀態(tài)
PS >flutter devices
// 檢查Windows開發(fā)相關(guān)有沒有安裝
PS >flutter doctor
前提二:在國內(nèi)開發(fā)嗎?請?jiān)O(shè)置鏡像站的環(huán)境變量
官方教程:在中國網(wǎng)絡(luò)環(huán)境下使用 Flutter
因?yàn)樵趪鴥?nèi)訪問速度很慢或者有的地區(qū)的童鞋根本就不能訪問官方的包管理,而在創(chuàng)建應(yīng)用的時(shí)候,會(huì)去包管理服務(wù)器下載一些依賴包,就會(huì)出現(xiàn)400系列錯(cuò)誤或者500系列錯(cuò)誤(因?yàn)榫W(wǎng)絡(luò)原因,官方的服務(wù)器會(huì)隨時(shí)掛掉)
注意:官方給出了好多個(gè)鏡像地址,經(jīng)過使用后,推薦CNNIC,或Flutter社區(qū),發(fā)現(xiàn)清華的不是太穩(wěn)定,上海交大的十分不穩(wěn)定。具體鏡像情況查看這個(gè)網(wǎng)址:Flutter 鏡像狀態(tài)檢測 (uptimerobot.com)
官方教程中沒有windows平臺(tái)設(shè)置方法,開發(fā)windows的童鞋下按照以下步驟設(shè)置:
1. win+s 搜索env打開環(huán)境變量
2. 在系統(tǒng)變量中`新建`輸入PUB的環(huán)境變量。如:變量名:```PUB_HOSTED_URL``` ,變量值:```http://mirrors.cnnic.cn/dart-pub```
3. 和FLUTTER的,如:變量名:```FLUTTER_STORAGE_BASE_URL```,變量值:```http://mirrors.cnnic.cn/flutter```
4. 保存后重啟VS Code,注意前文的環(huán)境變量注入原理
創(chuàng)建應(yīng)用
// 簡單寫法
PS >flutter create yourappname
// 復(fù)雜寫法
PS >flutter create --template app --platforms linux,windows,android --project-name yourappname .\YourAppProjectFolderName\
// 為已有的應(yīng)用添加桌面支持(多個(gè)平臺(tái)名稱用英文逗號(hào)隔開,如:windows,linux,maos)
// *** 最后的`點(diǎn)`很重要,是當(dāng)前應(yīng)用目錄的意思,別忘了 ***
PS >flutter create --platforms=windows .
注意:項(xiàng)目名稱一定!一定!一定!不能有大寫,單詞之間想隔開用
_,dart不允許項(xiàng)目名稱有大寫。但是,文件夾名字可以隨便寫大小寫??
運(yùn)行應(yīng)用
// 運(yùn)行當(dāng)前app的命令,會(huì)自動(dòng)按照當(dāng)前選定的設(shè)備進(jìn)行編譯。-v 參數(shù)是打印詳細(xì)日志
PS >flutter run -v
如果是要開發(fā)安卓APP的小童鞋,要注意了。
####### 1. Gradle生成工具
咱們安卓的Gradle生成工具要訪問國外的鏈接,不然編譯就會(huì)出現(xiàn)各種報(bào)錯(cuò)問題,如卡在Gradle task assembleDebug。遇到這個(gè)問題,可能需要替換成國內(nèi)的包源。
這里只介紹項(xiàng)目內(nèi)的更換Gradle包源的辦法,全局更換方法請google就是。
找到項(xiàng)目中的:\android\build.gradle 這個(gè)文件,對(duì)照如下代碼修改
buildscript {
ext.kotlin_version = '1.3.50'
repositories {
//google()
//jcenter()
// 下面兩句是阿里包源
maven { url 'https://maven.aliyun.com/repository/google/' }
maven { url 'https://maven.aliyun.com/repository/jcenter/'}
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
//google()
//jcenter()
// 下面兩句是阿里包源
maven { url 'https://maven.aliyun.com/repository/google/' }
maven { url 'https://maven.aliyun.com/repository/jcenter/'}
}
}
####### 2. JDK版本之謎
咱們的Flutter兼容的JDK版本是個(gè)謎,編譯會(huì)報(bào)各種錯(cuò)誤,網(wǎng)上有人說是只兼容JDK8,更為新的版本有問題。JDK有幾個(gè)下載渠道,在Oracle下載的應(yīng)該沒有問題。
強(qiáng)烈建議不要!不要!不要在OpenJDK這個(gè)Oracle的換皮網(wǎng)站下載,我下的所有的二進(jìn)制壓縮包發(fā)現(xiàn)都不全,最后上微軟官網(wǎng)下了一個(gè),配置環(huán)境變量(記得要重啟vs code)后正常使用,就是版本號(hào)奇奇怪怪的。
20201/04/09熱點(diǎn)更新:伴隨著微軟在Google和甲骨文的Java專利官司中勝訴,微軟立馬發(fā)布自己的OpenJDK——Microsoft Build of OpenJDK,以后可以到微軟官網(wǎng)下載JDK。
####### 3. 編譯出錯(cuò)怎么查看更多信息
安卓采用Gradle進(jìn)行構(gòu)建,所以當(dāng)出錯(cuò)后我們自然使用Gradle查看更多信息,那么Gradle在哪里呢?
// 在你的項(xiàng)目路徑下的這里
./android/gradlew
知道它在哪里,終端中錯(cuò)誤的相關(guān)建議就知道怎么做了。下圖里的* Try: 后面的內(nèi)容是指的Gradle而言,所以我們就能通過這樣的命令查看調(diào)用堆棧信息:
PS >./android/gradlew compileDebug --stacktrace -info

####### 4. 常見問題:
1. 'Finished with error: Gradle task assembleDebug failed with exit code 1'
出現(xiàn)這個(gè)報(bào)錯(cuò)要檢查下JAVA的環(huán)境變量設(shè)置是否正確,VS Code有沒有重啟。
2. `javax.net.ssl.SSLException`
出現(xiàn)這個(gè)異常一般是JDK版本不兼容,更換為Flutter兼容SDK即可。
3. `Gradle "Could not open buildscript class cache"`
出現(xiàn)這個(gè)報(bào)錯(cuò)一般關(guān)閉VS Code,刪除C盤用戶目錄下.gradle下caches文件夾。還不能解決有可能是JDK版本不兼容,更換為Flutter兼容SDK即可。
4. 出現(xiàn)運(yùn)行錯(cuò)誤,打印日志中提示需要 Android SDK Build tools 的某個(gè)版本
出現(xiàn)這個(gè)問題,打開Andorid SDK管理工具,勾選下載Android SDK Build tools下的對(duì)應(yīng)版本即可
開發(fā)文檔
用戶界面
Widgets介紹
這個(gè)章節(jié)介紹,F(xiàn)lutter中一切UI元素都是Widget(組件),這是個(gè)基類。所以就肯定有繼承于基類的通用的基礎(chǔ)組件,和由基礎(chǔ)組件組成應(yīng)用于不同場景的高級(jí)組件,也肯定可以自己編寫組件類。雖然邏輯抽象反而會(huì)增加代碼復(fù)雜度,面向?qū)ο螅ㄔ诿嫦騏I對(duì)象上)真的是的好工具。
其中,我覺得傳達(dá)出一個(gè)很重要的概念:組件和狀態(tài)分離。
如果熟悉MVVM模式(vue.js、WPF)的童鞋一定很熟悉UI與數(shù)據(jù)分離的模式,通過更新數(shù)據(jù)就可以達(dá)到更新UI的效果。而Flutter采用的是另外一套MVU模式,我個(gè)人感覺是腳本+閉包的嵌套寫法。
初次接觸這種寫法剛開始肯定會(huì)被搞蒙:代碼和數(shù)據(jù)混雜、作用域混亂、又臭又長,代碼層級(jí)巨深,閱讀體驗(yàn)極差等。但是,它也有它的好處,就是一致性強(qiáng)。數(shù)據(jù)和UI在一起,清晰的代碼走向。所以,在一開始學(xué)習(xí)的時(shí)候,就要做好使用好面向?qū)ο筮@個(gè)工具,將可以抽離的模塊形成類、方法、對(duì)象等。而,代碼的簡潔和性能之道也是需要在后續(xù)的使用過程中持續(xù)提高的,可能在使用了flutter幾年之后,你仍然能提升寫法使你的代碼更加優(yōu)雅。
布局構(gòu)建
Fluter中的布局
筆者認(rèn)為的布局組件結(jié)構(gòu)表如下:
| 級(jí)別 | 標(biāo)準(zhǔn) widgets | Material widgets |
|---|---|---|
| 基礎(chǔ) | Row、Column、Center、Container、Stack | |
| 高級(jí) | ListView、GridView、Table | Card、ListTile、DataTable |
####### 1. 布局要點(diǎn)
第一,常規(guī)布局使用基礎(chǔ)基別的標(biāo)準(zhǔn)widgets即可,平面布局Row、Colume互相嵌套再加上Container,Container就是一個(gè)常見UI框架的容器大集合,和div很像。層次布局使用Stack嵌套。
第二,在一些局部的復(fù)雜數(shù)據(jù)呈現(xiàn)、批量同類數(shù)據(jù)和特定局部布局中使用高級(jí)的布局組件可以簡化布局工作。
最后,因?yàn)镸VU的代碼編寫方式是高度嵌套的結(jié)構(gòu),為了最大限度地減少嵌套深入產(chǎn)生的代碼閱讀體驗(yàn)差,可以在變量和函數(shù)中實(shí)現(xiàn) UI 的各個(gè)部分。
布局約束[新增]
總結(jié)起來就是:
子組件的成長空間由父組件決定,而父組件和現(xiàn)實(shí)世界相同則有兩種:放任自流和進(jìn)行約束,放任自流又分為自私和兒控,約束又分為寬松約束和嚴(yán)格約束。
注:這里是胡亂分類取名,搏君一笑爾,會(huì)意即可,切勿認(rèn)真。
- 放任自流,子組件可以充分發(fā)揮自己的長度,不受屏幕限制。容易產(chǎn)生越界行為。
- 自私指的是,自己受父控件約束,子控件不管。
- 兒控指的是,既受父控件約束,在這個(gè)前提下能跟子控件一邊大就一邊大,沒兒子跟才父組件一樣大。
- 寬松約束是指下限可以跟上限不同,子組件在中間隨意,越界不行。
- 嚴(yán)格約束是指下限和上限一致,子組件必須和父組件的約束一樣大。
So,常見組件的約束分類如下:
| 父組件類型 | 約束類型 | 組件 |
|---|---|---|
| 放任自流 | 自私 | Row、Column、UnconstrainedBox、OverflowBox |
| 兒控 | Container、FittedBox | |
| 約束 | 寬松約束 | Center、Align、ConstrainedBox、LimitedBox、Flexible、Scaffold |
| 嚴(yán)格約束 | App、Expanded、SizedBox.expand() |
####### 容易忽略的點(diǎn)
- Row不會(huì)對(duì)子組件有任何約束,所以在Row中直接放置Text,Text接收不到任何約束。在文本過長的情況下,會(huì)直接超出屏幕。為了能實(shí)現(xiàn)文本自動(dòng)換行的效果,需要給Text加上Expanded,因?yàn)镋xpanded的寬度為自動(dòng)填充計(jì)算出來的,由它來傳遞約束給Text,Text就能根據(jù)約束來進(jìn)行換行。
- UnconstrainedBox和OverflowBox雖然對(duì)子組件無限制,但是前者在子組件越界了會(huì)管一下報(bào)錯(cuò),后者不會(huì)管。
- FittedBox它有的空間都會(huì)給兒子,但是兒子不能貪心要天上的月亮(無窮無盡),不然什么都沒有。
- LimitedBox能對(duì)子組件進(jìn)行限制,但是卻需要它的父組件對(duì)它沒有限制。
- Flexible和Expanded都會(huì)忽略其子控件的寬度,而Flexible只是會(huì)讓瘦弱的孩子得到剛適合它的大小。
添加互動(dòng)
互動(dòng)中最核心的還是狀態(tài)的問題,Widget分為無狀態(tài)和有狀態(tài)的。無狀態(tài)的組件意味著數(shù)據(jù)無關(guān),創(chuàng)建后就UI一直不變到生命消亡。有狀態(tài)組件有著狀態(tài)(數(shù)據(jù)),在生命周期內(nèi)數(shù)據(jù)會(huì)發(fā)生變化而影響到UI變化。
看著這種區(qū)別涇渭分明,實(shí)則不用過多區(qū)別。其實(shí)它是一個(gè)層級(jí)關(guān)系,最基礎(chǔ)的組件都是無狀態(tài)的,有狀態(tài)的組件只是由無狀態(tài)組件組合成了一個(gè)能單獨(dú)支撐某一特定類型業(yè)務(wù)數(shù)據(jù)呈現(xiàn)的層面。實(shí)際上它的狀態(tài)更新導(dǎo)致的UI更新,也是對(duì)子無狀態(tài)組件的一次銷毀到重新構(gòu)建的過程。
而互動(dòng)中的狀態(tài)管理的意思是,對(duì)于有狀態(tài)的組件應(yīng)該怎么樣管理狀態(tài)??偨Y(jié)一句話就是:
業(yè)務(wù)狀態(tài)業(yè)務(wù)控件管,界面狀態(tài)自己管。和人相關(guān)父親管,自身狀態(tài)自己管。
其實(shí),熟悉MVVM的童鞋這個(gè)就很好理解,狀態(tài)對(duì)應(yīng)ViewModel,我們會(huì)在Control和View層級(jí)對(duì)應(yīng)相應(yīng)的ViewModel。而控件自身的顯示狀態(tài)、動(dòng)畫、效果等均由控件自身(也就是樣式)自己來維護(hù)。體現(xiàn)的就是一個(gè)作用域思想,也可以理解成層級(jí)關(guān)系。讓合適的層級(jí)干它能干的事情就行,不去可以擴(kuò)大狀態(tài)管轄范圍也不縮小狀態(tài)范圍還得進(jìn)行狀態(tài)同步。
這里介紹一個(gè)我認(rèn)為的設(shè)計(jì)原則:
能做無狀態(tài)的Widget就做成無狀態(tài),減少狀態(tài)管理的位置,進(jìn)而減少狀態(tài)耦合和代碼復(fù)雜度,增加狀態(tài)的聚合度。通過父Widget狀態(tài)更新讓Flutter重新構(gòu)建這個(gè)無狀態(tài)Widget達(dá)到更新界面的目的。
Windows窗口美化
一般來說,任何一個(gè)桌面商業(yè)軟件,都必然是要將默認(rèn)系統(tǒng)窗口的窗體去掉,自己進(jìn)行修飾的。修飾內(nèi)容就主要包括:標(biāo)題欄,三金剛鍵,標(biāo)題拖動(dòng),窗體大小,窗體位置,邊框和陰影,窗體背景。
一般對(duì)于win32程序員來說,這根本不是一個(gè)問題,因?yàn)樗麄儠?huì)自己對(duì)flutter項(xiàng)目中的windows文件夾中的win32代碼進(jìn)行修改,實(shí)現(xiàn)他們想要的任何窗體效果。但是對(duì)于不熟悉win32的程序員來說,這就是一件特別難受的事情了。
很遺憾,直至2021/04/21,windows的CSD(Client-Side Decoration)支持還未得到官方支持,有興趣的可以去這個(gè)issue了解信息Desktop Client Side Decoration support · Issue #31373。
其中就包含一個(gè)解決方案,是一個(gè)開發(fā)者也是遇到需要美化窗體時(shí),看到這條issue就自己動(dòng)手實(shí)現(xiàn)了一個(gè)庫來解決這個(gè)問題。pub鏈接:bitsdojo_window,感謝他的付出。
同時(shí),開發(fā)者還貼心的錄制了視頻放在某Y屏蔽網(wǎng)站上,B站的搬運(yùn)在此:Flutter desktop - 自定義窗口標(biāo)題欄包含Windows窗體的最大化最小化和關(guān)閉按鈕
這里需要注意:因?yàn)镕lutter對(duì)于各個(gè)平臺(tái)的runner實(shí)現(xiàn)均放在對(duì)應(yīng)平臺(tái)的文件夾下,windows文件下就有對(duì)應(yīng)源代碼windows窗體相關(guān)的win32窗口和dart的封裝,但是經(jīng)過一番研究和修改后發(fā)現(xiàn)它的主要結(jié)構(gòu)還是為
主窗口+flutter子窗口,他們都不是layer層。主窗口為進(jìn)程的啟動(dòng)窗口,子窗口用于放置flutter的app內(nèi)容??赏ㄟ^修改實(shí)現(xiàn)移除默認(rèn)windows窗口,增加頂部拖動(dòng),增加按鈕,增加陰影等一系列功能,但是不能增加背景透明度達(dá)到類似win7的毛玻璃效果。所以要實(shí)現(xiàn)背景透明類似的效果需要等待官方的實(shí)現(xiàn)。
未完待續(xù)...