Flutter實(shí)戰(zhàn)指南(移動(dòng)終端-應(yīng)用程序-程序設(shè)計(jì))_第1頁(yè)
Flutter實(shí)戰(zhàn)指南(移動(dòng)終端-應(yīng)用程序-程序設(shè)計(jì))_第2頁(yè)
Flutter實(shí)戰(zhàn)指南(移動(dòng)終端-應(yīng)用程序-程序設(shè)計(jì))_第3頁(yè)
Flutter實(shí)戰(zhàn)指南(移動(dòng)終端-應(yīng)用程序-程序設(shè)計(jì))_第4頁(yè)
Flutter實(shí)戰(zhàn)指南(移動(dòng)終端-應(yīng)用程序-程序設(shè)計(jì))_第5頁(yè)
已閱讀5頁(yè),還剩305頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

Flutter實(shí)戰(zhàn)指南移動(dòng)終端-應(yīng)用程序-程序設(shè)計(jì)目錄TOC\h\h基礎(chǔ)篇\h第1章Flutter簡(jiǎn)介\h1.1什么是Flutter\h1.2Flutter的架構(gòu)\h1.3在macOS下安裝Flutter\h1.4在macOS下安裝VisualStudioCode\h1.5在Windows下安裝Flutter\h1.6在Windows下安裝VisualStudioCode\h1.7Flutter中的MaterialDesign體系\h第2章深入理解Flutter基礎(chǔ)知識(shí)和小部件概念\h2.1創(chuàng)建一個(gè)Flutter項(xiàng)目\h2.2Flutter目錄結(jié)構(gòu)及main文件\h2.3Flutter中小部件的概念\h2.4創(chuàng)建Flutter小部件\h2.5小部件中的build方法\h2.6添加Scaffold頁(yè)面\h2.7深入學(xué)習(xí)Dart語(yǔ)法\h2.8使用Card小部件和圖片\h2.9官方文檔及使用按鈕RaisedButton\h2.10創(chuàng)建StatefulWidget小部件\h2.11在StatefulWidget中管理數(shù)據(jù)\h2.12在StatefulWidget小部件中添加數(shù)據(jù)\h2.13把小部件拆分到單獨(dú)的文件中\(zhòng)h2.14使用自定義小部件\h2.15給StatefulWidget傳遞參數(shù)\h2.16深入學(xué)習(xí)生命周期\h2.17深入學(xué)習(xí)Google的MaterialDesign設(shè)計(jì)體系\h2.18Dart語(yǔ)言特性及位置參數(shù)與可選參數(shù)\h2.19Flutter中解除狀態(tài)的特性\h2.20理解Dart語(yǔ)言中的final和const\h2.21總結(jié)\h第3章調(diào)試Flutter應(yīng)用程序\h3.1解決語(yǔ)法錯(cuò)誤\h3.2運(yùn)行時(shí)錯(cuò)誤和運(yùn)行時(shí)日志消息\h3.3處理邏輯錯(cuò)誤\h3.4使用debug斷點(diǎn)調(diào)試\h3.5UI調(diào)試及視覺(jué)幫助工具\(yùn)h第4章在不同設(shè)備上運(yùn)行Flutter應(yīng)用程序\h4.1將App運(yùn)行到Android模擬器上\h4.2將Flutter應(yīng)用運(yùn)行到Android設(shè)備上\h4.3將App運(yùn)行到iOS模擬器和設(shè)備上\h第5章列表ListView小部件和條件過(guò)濾\h5.1使用ListView創(chuàng)建滾動(dòng)列表\h5.2優(yōu)化列表加載功能\h5.3根據(jù)條件渲染列表內(nèi)容\h5.4根據(jù)條件渲染內(nèi)容的替代方案\h5.5總結(jié)\h第6章Flutter頁(yè)面導(dǎo)航\h6.1在App中添加多個(gè)頁(yè)面\h6.2給導(dǎo)航頁(yè)面添加按鈕\h6.3實(shí)現(xiàn)基本導(dǎo)航功能\h6.4優(yōu)化詳情頁(yè)面\h6.5通過(guò)Push給頁(yè)面?zhèn)鬟f數(shù)據(jù)\h6.6通過(guò)Pop獲取頁(yè)面返回的數(shù)據(jù)\h6.7給導(dǎo)航頁(yè)面中的按鈕添加單擊事件\h6.8添加登錄頁(yè)面并切換頁(yè)面\h6.9抽屜式導(dǎo)航\h6.10使用Tab標(biāo)簽頁(yè)導(dǎo)航頁(yè)面\h6.11命名路徑\h6.12解析導(dǎo)航路徑數(shù)據(jù)\h6.13導(dǎo)航頁(yè)面的整理與優(yōu)化\h6.14使用導(dǎo)航路徑生成器\h6.15對(duì)話框\h6.16模態(tài)彈出層\h6.17總結(jié)\h第7章處理用戶輸入\h7.1使用文本框TextField并保存用戶輸入內(nèi)容\h7.2配置文本框TextField\h7.3設(shè)置文本框TextField樣式\h7.4保存文本框中內(nèi)容\h7.5優(yōu)化文本框顯示\h7.6使用開(kāi)關(guān)Switch小部件\h7.7總結(jié)\h第8章深入學(xué)習(xí)Flutter小部件\h8.1Flutter官網(wǎng)探索小部件\h8.2使用不同的小部件完成同一個(gè)目標(biāo)\h8.3文本小部件Text和行小部件Row\h8.4修飾小部件BoxDecoration\h8.5理解Expanded和Flexible\h8.6添加背景圖像\h8.7圖標(biāo)小部件Icon\h8.8封裝小部件\h8.9重構(gòu)項(xiàng)目代碼\h8.10創(chuàng)建標(biāo)準(zhǔn)化的小部件\h8.11封裝小部件的方法\h8.12Flutter中響應(yīng)式設(shè)計(jì)\h8.13使用MediaQuery\h8.14ListView中使用MediaQuery\h8.15使用GestureDetector添加監(jiān)聽(tīng)\h8.16總結(jié)\h第9章Form表單\h9.1表單文本框TextFormField\h9.2Form表單驗(yàn)證\h9.3表單Form的高級(jí)驗(yàn)證\h9.4關(guān)閉設(shè)備鍵盤\h9.5提交表單數(shù)據(jù)\h9.6把表單數(shù)據(jù)保存到列表\h9.7重用創(chuàng)建資訊頁(yè)面\h9.8表單設(shè)置初始值\h9.9更新數(shù)據(jù)\h9.10總結(jié)\h高級(jí)篇\h第10章優(yōu)化Flutter應(yīng)用功能\h10.1優(yōu)化ListTile\h10.2通過(guò)Dismissible小部件實(shí)現(xiàn)滑動(dòng)刪除\h10.3監(jiān)聽(tīng)滑動(dòng)手勢(shì)刪除數(shù)據(jù)及總結(jié)\h第11章?tīng)顟B(tài)集中管理ScopeModel\h11.1優(yōu)化Flutter狀態(tài)管理\h11.2自定義實(shí)體類\h11.3創(chuàng)建ScopedModel\h11.4與ScopedModel建立聯(lián)系\h11.5使用ScopedModel編輯和刪除\h11.6收藏功能\h11.7使用notifyListeners()方法\h11.8過(guò)濾收藏的內(nèi)容\h11.9添加用戶實(shí)體\h11.10使用mix特性合并模型\h11.11連接模型和共享數(shù)據(jù)\h11.12總結(jié)\h第12章Flutter與HTTP\h12.1后端服務(wù)接口\h12.2Flutter發(fā)送POST請(qǐng)求\h12.3使用請(qǐng)求響應(yīng)結(jié)果\h12.4從服務(wù)器端獲取數(shù)據(jù)\h12.5實(shí)現(xiàn)加載條\h12.6按鈕顯示加載條\h12.7通過(guò)HTTP更新數(shù)據(jù)\h12.8通過(guò)Http刪除內(nèi)容\h12.9下拉頁(yè)面刷新\h12.10占位圖片\h12.11優(yōu)化ScopedModel\h12.12處理HTTP響應(yīng)錯(cuò)誤\h12.13使用async和await\h12.14總結(jié)\h第13章權(quán)限認(rèn)證\h13.1Flutter中如何使用權(quán)限\h13.2確認(rèn)密碼文本框\h13.3用戶注冊(cè)\h13.4處理注冊(cè)過(guò)程中的異常\h13.5用戶注冊(cè)加載條\h13.6用戶登錄\h13.7訪問(wèn)受保護(hù)資源\h13.8存儲(chǔ)token\h13.9自動(dòng)登錄\h13.10用戶退出\h13.11自動(dòng)退出\h13.12自動(dòng)退出跳轉(zhuǎn)\h13.13優(yōu)化用戶登錄\h13.14添加收藏功能\h13.15獲取收藏狀態(tài)\h13.16根據(jù)條件顯示列表和總結(jié)\h第14章訪問(wèn)相機(jī)和圖庫(kù)\h14.1選擇圖片小部件\h14.2使用圖片選擇器UI\h14.3使用ImagePicker選擇圖片\h14.4圖片預(yù)覽\h14.5上傳圖片\h14.6上傳圖片到服務(wù)器端\h14.7編輯上傳的圖片\h14.8總結(jié)\h第15章Flutter動(dòng)畫效果\h15.1浮動(dòng)按鈕\h15.2添加動(dòng)畫效果\h15.3旋轉(zhuǎn)動(dòng)畫效果\h15.4漸變動(dòng)畫效果\h15.5滑動(dòng)動(dòng)畫效果\h15.6Flutter中的Hero和Sliver\h15.7自定義切換頁(yè)面動(dòng)畫效果\h第16章優(yōu)化應(yīng)用\h16.1優(yōu)化自動(dòng)退出\h16.2優(yōu)化編輯功能和收藏功能\h16.3使用analyze命令優(yōu)化項(xiàng)目\h第17章使用平臺(tái)特有的小部件\h17.1根據(jù)平臺(tái)的不同顯示不同的小部件\h17.2根據(jù)不同的平臺(tái)顯示不同的主題\h第18章Flutter跨平臺(tái)交互\h18.1Flutter與原生代碼交互\h18.2編寫Android端原生代碼并與Flutter交互\h18.3編寫iOS端原生代碼與Flutter交互\h第19章發(fā)布Flutter應(yīng)用\h19.1設(shè)置應(yīng)用圖標(biāo)\h19.2給App添加閃屏\h19.3Android打包和發(fā)布\h19.4iOS打包和發(fā)布\h第20章總結(jié)與回顧基礎(chǔ)篇相信許多移動(dòng)應(yīng)用開(kāi)發(fā)者在開(kāi)發(fā)過(guò)程中遇到過(guò)和我同樣問(wèn)題,開(kāi)發(fā)一套原生的應(yīng)用程序,需要運(yùn)行在iOS和Android兩個(gè)不同的平臺(tái),為此我們至少要學(xué)習(xí)Java、Object-C、Swift等兩到三種語(yǔ)言來(lái)滿足這樣的需求,占用了我們大量的時(shí)間和精力,而且還要維護(hù)不同的代碼庫(kù),或者有的開(kāi)發(fā)者使用Web的H5來(lái)實(shí)現(xiàn)這種跨平臺(tái)的應(yīng)用,但H5通常跟設(shè)備操作系統(tǒng)不是太友好,往往受瀏覽器版本和移動(dòng)設(shè)備中操作系統(tǒng)的限制。再有就是采用加殼的技術(shù)來(lái)滿足這種跨平臺(tái)的需求,但是就性能來(lái)說(shuō)會(huì)很糟糕?;谝陨线@些問(wèn)題的存在,F(xiàn)lutter誕生了,成為移動(dòng)應(yīng)用領(lǐng)域里很熱門的一項(xiàng)技術(shù)。大的互聯(lián)網(wǎng)平臺(tái)都開(kāi)始關(guān)注并使用這項(xiàng)技術(shù)去開(kāi)發(fā)它們的移動(dòng)應(yīng)用。大家將從本書基礎(chǔ)篇學(xué)習(xí)到如何使用一種語(yǔ)言、一個(gè)代碼庫(kù)構(gòu)建跨平臺(tái)移動(dòng)App,內(nèi)容包括如何構(gòu)建小部件,如何使用這些小部件搭建你的應(yīng)用。大家將循序漸進(jìn)地了解怎么使用Flutter構(gòu)建一個(gè)App。這里給大家建議是結(jié)合書中的內(nèi)容進(jìn)行編碼實(shí)踐,現(xiàn)在我們就一起學(xué)習(xí)Flutter,相信它會(huì)給你帶來(lái)一種神奇的體驗(yàn)。為了提高學(xué)習(xí)效率,作者提供在線答疑服務(wù),網(wǎng)址//,郵箱r80hou@或加QQ群:169055795。基礎(chǔ)篇包括了以下幾章:第1章Flutter簡(jiǎn)介介紹Flutter的一些發(fā)展情況和概括性地總結(jié)Flutter的技術(shù)架構(gòu),讓你快速地了解Flutter,以及在不同的操作系統(tǒng)上安裝Flutter的運(yùn)行環(huán)境和IDE。第2章深入理解Flutter基礎(chǔ)知識(shí)和小部件概念深入學(xué)習(xí)Flutter和Dart,以及如何使用Flutter構(gòu)建移動(dòng)App。這一章會(huì)讓你了解到關(guān)于小部件的核心基礎(chǔ)知識(shí),使用學(xué)到的小部件構(gòu)建第一個(gè)Flutter項(xiàng)目。第3章調(diào)試Flutter應(yīng)用程序定位Flutter開(kāi)發(fā)過(guò)程中不同類型的錯(cuò)誤,學(xué)習(xí)不同的解決方式。第4章在不同設(shè)備上運(yùn)行Flutter應(yīng)用程序?qū)pp運(yùn)行到iOS和Android模擬器及真實(shí)設(shè)備上。第5章列表ListView小部件和條件過(guò)濾深入學(xué)習(xí)ListView小部件,并根據(jù)條件渲染ListView中的內(nèi)容。第6章Flutter頁(yè)面導(dǎo)航學(xué)習(xí)如何構(gòu)建頁(yè)面導(dǎo)航,然后通過(guò)Flutter進(jìn)行頁(yè)面切換,以及如何向前、向后傳遞數(shù)據(jù)。第7章處理用戶輸入學(xué)習(xí)使用基本表單小部件與用戶交互并保存用戶輸入的內(nèi)容。第8章深入學(xué)習(xí)Flutter小部件了解查找小部件的方式及配置小部件的方法。第9章Form表單學(xué)習(xí)以更好的方式處理用戶輸入,驗(yàn)證輸入內(nèi)容并保存它們。通過(guò)本篇的學(xué)習(xí),你可以了解到Flutter、Dart及小部件的概念;學(xué)會(huì)在macOS和Windows上搭建Flutter的環(huán)境;掌握調(diào)試技巧和竅門;理解基于堆棧的導(dǎo)航;處理并驗(yàn)證用戶的輸入,從而搭建出具有基本功能的App。第1章Flutter簡(jiǎn)介Flutter實(shí)際上是一個(gè)包含多種內(nèi)容的軟件包,你可以說(shuō)它是用于創(chuàng)建移動(dòng)2D應(yīng)用程序的SDK軟件開(kāi)發(fā)工具包。Flutter的軟件包中最重要的就是編程框架,框架使用Dart作為編程語(yǔ)言,通過(guò)本章的學(xué)習(xí)你將對(duì)Flutter的特性和開(kāi)發(fā)技術(shù)有深入的了解。1.1什么是FlutterFlutter是一個(gè)基于Dart語(yǔ)言的框架,這個(gè)框架包含可以直接使用的類。這樣你就不必從頭開(kāi)始編寫所有內(nèi)容。例如,F(xiàn)lutter附帶了大量的小部件,小部件實(shí)際上就是UI元素,例如按鈕、Tab頁(yè)、列表等,所以你不必編寫所有內(nèi)容,而是可以使用Flutter框架中的所有這些工具,添加自己的代碼和實(shí)現(xiàn)自己的邏輯,然后使用這些功能構(gòu)建原生應(yīng)用程序。因此,只需使用一種語(yǔ)言Dart編寫代碼,你不必學(xué)習(xí)Java或Swift或其他任何東西。在熟悉了Flutter框架功能后,你可以根據(jù)不同平臺(tái),編寫特定平臺(tái)的代碼,這也是我將在本書中介紹的內(nèi)容。Flutter不只是Dart編碼,它還是一組工具集合,允許你在設(shè)備上測(cè)試編寫的應(yīng)用程序,具有很酷的功能,例如自動(dòng)重新加載代碼中的任何內(nèi)容,以及在模擬器上運(yùn)行應(yīng)用程序,非常方便。Flutter還提供了構(gòu)建工具,以便將Dart代碼構(gòu)建打包,并上傳到AppleStore或Android應(yīng)用商店中。Flutter會(huì)將Dart代碼編譯為本機(jī)代碼,因此,F(xiàn)lutter既是編程框架又是工具集合。為了更直觀地理解Flutter,我們看一下Flutter與Dart關(guān)系圖,如圖1.1所示,F(xiàn)lutter建立在Dart上。Dart是編程語(yǔ)言,然后Flutter提供了編程框架,它與Dart有很好的關(guān)聯(lián),或者在Dart上堆建。Flutter提供了許多實(shí)用功能和大量小部件,還包括構(gòu)建測(cè)試應(yīng)用程序的SDK等工具,這就是Flutter。這是你將從頭開(kāi)始學(xué)習(xí)的,我們將使用Flutter與Dart一起構(gòu)建原生移動(dòng)應(yīng)用程序并將它們發(fā)布到應(yīng)用商店上。圖1.1Flutter與Dart關(guān)系圖1.2Flutter的架構(gòu)Flutter的架構(gòu)是什么樣的,以及它的核心概念是什么?使用Flutter構(gòu)建好App后,你會(huì)發(fā)現(xiàn)App只是一個(gè)小部件樹(shù),可以將其視為應(yīng)用程序中的UI元素,整個(gè)應(yīng)用程序是一個(gè)UI元素,它包含子元素,例如導(dǎo)航欄;或者是一些文字,又或者是用戶的輸入框,也可以是一個(gè)按鈕。我們可以把這些小部件放到可視化的小部件中,例如行小部件、列小部件,然后對(duì)行和列進(jìn)行排列組合的布局。Flutter是擁抱差異的,這意味著你可以使用一種編程語(yǔ)言編寫運(yùn)行在iOS和Android平臺(tái)的應(yīng)用。同時(shí)你也可以根據(jù)iOS和Android平臺(tái)的差異,去分別開(kāi)發(fā)各自平臺(tái)的代碼,這就是Flutter很核心的一個(gè)概念。圖1.2一切都是小部件在Flutter中一切都是小部件,如圖1.2所示的就是開(kāi)發(fā)完成后的一個(gè)頁(yè)面,在這個(gè)頁(yè)面中,使用了大量的小部件,但實(shí)際上比這里標(biāo)示的還要多,例如按鈕是一個(gè)小部件,它上面的文字是另外一個(gè)小部件,整個(gè)頁(yè)面也是一個(gè)小部件,這樣就形成了一個(gè)小部件樹(shù)。應(yīng)用是一個(gè)小部件,它包含了不同的頁(yè)面,然后每個(gè)頁(yè)面也是小部件,頁(yè)面中包含的內(nèi)容也是小部件,頁(yè)面和頁(yè)面之間還可以切換。下一個(gè)核心的問(wèn)題是怎樣把Flutter中的Dart編碼轉(zhuǎn)換成原生應(yīng)用的代碼。我們使用Dart語(yǔ)言編寫代碼,然后借助FlutterAPI編寫自己的小部件。那么怎樣才能編譯成iOS和Android的原生代碼呢?FlutterSDK幫助我們完成這項(xiàng)工作,你不必編寫任何原生的代碼,你只需要用Dart語(yǔ)言編寫,使用Flutter的功能,然后FlutterSDK就會(huì)完成代碼的編譯工作,以上就是Flutter提供給我們的全部功能,如圖1.3所示。下面我們就可以搭建開(kāi)發(fā)環(huán)境,開(kāi)發(fā)我們的第一個(gè)Flutter應(yīng)用程序了,并把它運(yùn)行到模擬器上。圖1.3Dart編碼轉(zhuǎn)換成原生應(yīng)用的代碼1.3在macOS下安裝FlutterFlutter在macOS和Windows上的安裝步驟不同,這節(jié)講解如何在macOS上安裝Flutter。如果你是Windows用戶請(qǐng)?zhí)^(guò)1.3和1.4節(jié),同樣如果你是macOS用戶請(qǐng)?zhí)^(guò)1.5和1.6節(jié),下面我們看一下安裝過(guò)程。下載并安裝Flutter的步驟如下:首先訪問(wèn)Flutter的官網(wǎng)https://flutter.dev/,瀏覽器將會(huì)顯示如圖1.4所示的頁(yè)面,單擊頁(yè)面右上方“Getstarted”,然后下載Flutter的穩(wěn)定版本。解壓文件到指定目錄,例如/flutter目錄下面,然后在終端運(yùn)行vim~/.bash_profile命令,配置環(huán)境變量,如圖1.5所示。配置好變量后,在終端運(yùn)行source./.bash_profile使配置生效,再運(yùn)行flutterdoctor命令,這個(gè)命令檢查環(huán)境是否正確,并向終端窗口顯示報(bào)告。DartSDK與Flutter捆綁在一起,沒(méi)有必要單獨(dú)安裝Dart。請(qǐng)仔細(xì)檢查輸出以了解可能需要安裝的其他軟件或執(zhí)行的其他任務(wù)(以粗體顯示)。如果沒(méi)有安裝Xcode,需要安裝一下Xcode9.0或以上版本。同樣,如果沒(méi)有安裝AndroidStudio,也需要安裝最新版本的AndroidStudio。再運(yùn)行flutterdoctor命令,如圖1.6所示,提示沒(méi)有可用的設(shè)備。圖1.4Flutter官方網(wǎng)站圖1.5配置Flutter環(huán)境變量運(yùn)行open-aSimulator命令打開(kāi)模擬器,然后通過(guò)命令創(chuàng)建我們的第一個(gè)FlutterApp。首先進(jìn)入項(xiàng)目目錄,我的項(xiàng)目目錄是根目錄下的flutter-app,然后運(yùn)行fluttercreatemy_app。Flutter會(huì)幫我們生成Flutter相關(guān)的文件,創(chuàng)建好后進(jìn)入my_app目錄,運(yùn)行flutterrun命令,這樣我們的第一個(gè)FlutterApp就創(chuàng)建好了,并成功運(yùn)行到模擬器上了,如圖1.7所示。圖1.6檢查環(huán)境是否正確圖1.7FlutterApp運(yùn)行在iOS模擬器上Flutter支持熱加載,完成啟動(dòng)后,單擊R鍵進(jìn)行熱加載。下面看一下如何將項(xiàng)目運(yùn)行到Android的模擬器上,打開(kāi)AndroidStudio,打開(kāi)一個(gè)已有的項(xiàng)目,就是我們剛才生成的my_app。首先需要?jiǎng)?chuàng)建一個(gè)模擬器,單擊頁(yè)面上方的“Tools”按鈕,然后單擊“AVDManager”按鈕創(chuàng)建一個(gè)Android模擬器,如圖1.8所示。選擇這個(gè)模擬器,單擊頁(yè)面右側(cè)的“run”按鈕,把我們的FlutterApp運(yùn)行到這個(gè)模擬器上。你可以使用AndroidStudio編寫代碼,也可以使用IntelliJIDEA,我們這里使用VisualStudioCode編寫。圖1.8創(chuàng)建一個(gè)Android模擬器1.4在macOS下安裝VisualStudioCode登錄網(wǎng)站/,如圖1.9所示,可以免費(fèi)安裝VisualStudioCode,像大多數(shù)IDE一樣,這個(gè)網(wǎng)站會(huì)自動(dòng)識(shí)別你的系統(tǒng),然后給你提供相應(yīng)的下載內(nèi)容,下載后執(zhí)行這個(gè)文件,完成安裝程序。安裝非常簡(jiǎn)單,沒(méi)什么特別之處,安裝完成后就可以運(yùn)行它了。在啟動(dòng)屏幕上選擇文件夾或文件,讓我們打開(kāi)之前創(chuàng)建好的Flutter項(xiàng)目,如圖1.10所示,然后它就會(huì)呈現(xiàn)在IDE中。除此之外還需安裝一些插件,使IDE對(duì)Flutter的支持更友好。單擊屏幕上方的“View”按鈕選擇“Extension”,然后搜索Flutter找到官方的Flutter插件,單擊“Install”按鈕,如圖1.11所示,同時(shí)它會(huì)把Dart作為它的依賴也安裝上,安裝完成后,單擊“Reload”按鈕,重新加載一下你的IDE。還有一個(gè)可選的插件需要安裝,那就是MaterialIconTheme。這個(gè)插件跟Flutter沒(méi)有直接關(guān)系,但它會(huì)使圖標(biāo)看起來(lái)更美觀。安裝完成后單擊“Explorer”按鈕,回到項(xiàng)目目錄,準(zhǔn)備開(kāi)始開(kāi)發(fā)FlutterApp。在main.dart文件中找到_incrementCounter()方法把_counter++改成_counter=_counter+2,如圖1.12所示,這樣單擊一次按鈕就會(huì)加2。圖1.9下載用于macOS的VisualStudioCode圖1.10使用VisualStudioCode打開(kāi)項(xiàng)目現(xiàn)在使用Flutter的熱加載功能,來(lái)到終端,按一下R鍵,F(xiàn)lutter就會(huì)執(zhí)行剛才的改動(dòng)。如果App卡住了,可以按Shift+R,去重新構(gòu)建并加載?;氐侥M器中,看起來(lái)沒(méi)有什么變化,但是當(dāng)我們單擊模擬器中的按鈕,會(huì)發(fā)現(xiàn)數(shù)字每次加2,從這就可以看出使用Flutter多神奇,以及使用它開(kāi)發(fā)多容易,熱加載會(huì)貫穿于我們整個(gè)App開(kāi)發(fā)過(guò)程中。書中還會(huì)介紹IDE的一些技巧,現(xiàn)在去看看怎樣在Windows系統(tǒng)中安裝Flutter,如果你是macOS用戶可以跳過(guò)下面兩節(jié)。圖1.11使用VisualStudioCode下載Flutter插件圖1.12編寫main.dart文件1.5在Windows下安裝Flutter下面看一下如何在Windows系統(tǒng)上安裝Flutter。首先訪問(wèn)官網(wǎng)https://flutter.dev/,單擊頁(yè)面右上方的“Getstarted”按鈕,然后選擇“Windows”,如圖1.13所示。第一步看一下系統(tǒng)的要求,在Windows下安裝Flutter需要Windows7SPI或更高的版本,硬盤空間也很重要,不能低于400MB,還需要安裝兩個(gè)工具,如圖1.14所示。WindowsPowerShell5.0在Windows10里已經(jīng)預(yù)安裝了,如果是Windows的其他版本需自己安裝。另外一個(gè)工具是Git,可以在官網(wǎng)/download/winG下載并安裝,Git的安裝很簡(jiǎn)單,確認(rèn)好硬盤空間后,單擊“下一步”按鈕操作就可以了。圖1.13Flutter官方網(wǎng)站圖1.14需要安裝的工具現(xiàn)在我們就開(kāi)始安裝Flutter,你可以從官網(wǎng)下載一個(gè)穩(wěn)定版本,如圖1.15所示。當(dāng)你下載時(shí),版本可能會(huì)與圖1.15所示的版本不同,但不管怎樣,你只要下載官網(wǎng)的穩(wěn)定版本就可以。圖1.15下載Flutter的穩(wěn)定版本下載完成后,把它解壓到一個(gè)目錄下,這個(gè)目錄不是你的App目錄,而是SDK目錄。SDK是軟件開(kāi)發(fā)工具包,可以在系統(tǒng)上全局安裝,然后從系統(tǒng)不同目錄下使用它來(lái)創(chuàng)建Flutter項(xiàng)目,并使用這個(gè)項(xiàng)目,例如我們解壓到D:\Progams\flutter目錄下。這個(gè)目錄可以自己指定。下一步進(jìn)入這個(gè)目錄,雙擊運(yùn)行flutter_console.bat這個(gè)文件,它會(huì)彈出一個(gè)Flutter命令窗口,可以在這個(gè)窗口中運(yùn)行Flutter命令,這里我們使用Windows自帶的命令提示符,在使用之前需要配置一下全局變量,目的是讓W(xué)indows能夠找到對(duì)應(yīng)的路徑,如圖1.16所示。選擇控制面板并單擊“用戶”按鈕,下一步單擊“我的環(huán)境變量”按鈕,然后編輯環(huán)境變量,單擊“新建”按鈕,輸入安裝的Flutter目錄下的bin目錄,然后單擊“確定”按鈕。圖1.16配置環(huán)境變量關(guān)閉所有的命令行,打開(kāi)一個(gè)新的命令行,輸入命令flutter,按下回車鍵。如果屏幕上顯示的內(nèi)容如圖1.17所示,說(shuō)明環(huán)境變量配置成功了,就可以在命令行中輸入Flutter相關(guān)命令了,這樣Flutter就安裝好了。圖1.17運(yùn)行命令flutter后顯示的內(nèi)容下一步安裝AndroidStudio,訪問(wèn)網(wǎng)站/studio下載并安裝,下載前需要同意一些協(xié)議,下載完成后,執(zhí)行安裝,確認(rèn)勾選了AndroidVirtualDevice這一項(xiàng),如圖1.18所示。圖1.18勾選AndroidVirtualDevice選擇安裝的路徑,可以使用默認(rèn)的安裝路徑,也可以自定義,再單擊“Next”按鈕,執(zhí)行安裝程序,安裝好后就可以啟動(dòng)AndroidStudio了。首次啟動(dòng)會(huì)彈出使用向?qū)?,提示你設(shè)置主題等個(gè)人偏好。選擇Android虛擬器這一步很重要,如圖1.19所示確認(rèn)勾選了AndroidVirtualDevice,然后檢查AndroidSDK的位置,這里使用默認(rèn)的配置,單擊“Next”按鈕,再單擊“Finish”按鈕。這里提示大家,這一步需要很長(zhǎng)的時(shí)間進(jìn)行加載,因?yàn)榘惭b過(guò)程中需要下載很多軟件包。圖1.19勾選Android虛擬器在命令提示符中輸入fluttercreatefirst_app來(lái)創(chuàng)建一個(gè)Flutter項(xiàng)目,項(xiàng)目名稱中只能使用下畫線,而不能使用空格和橫杠,然后按回車鍵,F(xiàn)lutter會(huì)自動(dòng)創(chuàng)建一些配置文件。創(chuàng)建完成后,打開(kāi)AndroidStudio,選擇一個(gè)存在的Android項(xiàng)目,就是剛才創(chuàng)建好的Flutter項(xiàng)目。打開(kāi)一個(gè)模擬器,因?yàn)殚_(kāi)發(fā)階段大部分功能是在模擬器上調(diào)試并開(kāi)發(fā)的,然后再到真實(shí)的設(shè)備上測(cè)試。單擊屏幕上方的“Tools”按鈕,選擇“AVDManager”按鈕,單擊“+CreateVirtualDevice...”按鈕創(chuàng)建一個(gè)新的模擬器,如圖1.20所示。首先選擇一個(gè)設(shè)備,然后頁(yè)面會(huì)顯示創(chuàng)建向?qū)А_@里需要選擇模擬器的系統(tǒng),請(qǐng)選擇使用最新的版本,單擊“Next”按鈕。最后配置Graphics,選擇Hardware,如圖1.21所示。單擊“Finish”按鈕,這樣這個(gè)模擬器設(shè)備就創(chuàng)建好了。單擊運(yùn)行圖標(biāo),如圖1.22所示,模擬器就顯示出來(lái)了。下一步需要在AndroidStudio中安裝缺少的依賴項(xiàng)和插件,單擊IDE右上方的“Installplugins”按鈕,如圖1.23所示,然后重啟。啟動(dòng)好后IDE右下角會(huì)有一個(gè)提示,如圖1.24所示,建議安裝插件,單擊“Configureplugins”按鈕,會(huì)彈出Flutter插件,單擊“Accept”按鈕,同時(shí)也會(huì)自動(dòng)安裝Dart插件,Android完成后需要再次重啟IDE?;氐矫钐崾痉翱冢\(yùn)行命令flutterdoctor,命令提示符窗口會(huì)提示漏掉了哪些內(nèi)容。圖1.20創(chuàng)建一個(gè)新的模擬器圖1.21配置Graphics圖1.22啟動(dòng)模擬器圖1.23安裝插件圖1.24配置插件回到AndroidStudio,單擊IDE右上角“?”運(yùn)行按鈕,運(yùn)行我們創(chuàng)建的這個(gè)Flutter項(xiàng)目,可以看到FlutterApp已經(jīng)運(yùn)行到模擬器上了,單擊“浮動(dòng)”按鈕,可以增加計(jì)數(shù)器,或者在項(xiàng)目的目錄下運(yùn)行命令flutterrun來(lái)啟動(dòng)。1.6在Windows下安裝VisualStudioCode我們使用VisualStudioCode,可通過(guò)網(wǎng)站/下載IDE,如圖1.25所示。這個(gè)IDE是免費(fèi)的,并且支持Flutter的擴(kuò)展,訪問(wèn)網(wǎng)站,它會(huì)根據(jù)你的系統(tǒng)提供一個(gè)適合的下載版本。下載并安裝IDE,安裝步驟簡(jiǎn)單,沒(méi)有什么特別需要說(shuō)明的,安裝完成后就可以運(yùn)行它了。圖1.25在Windows下下載安裝VisualStudioCode為了使這個(gè)IDE更好用,需要添加一些插件,單擊“Extension”圖標(biāo),如圖1.26所示。搜索Flutter插件,安裝官方的Flutter插件,Dart會(huì)隨這個(gè)插件一起安裝,安裝完成后,重啟IDE。圖1.26使用VisualStudioCode下載Flutter插件另外,還要安裝一個(gè)插件MaterialIconTheme,這個(gè)插件與Flutter安裝無(wú)關(guān),它只是會(huì)使IDE變得美觀。在項(xiàng)目目錄下找到main.dart文件,然后到incrementCounter()方法里,把_counter++改成_counter=_counter+2,如圖1.27所示。圖1.27編寫main.dart文件這樣每次單擊“浮動(dòng)”按鈕就會(huì)加2。來(lái)到命令行窗口,不需要使用Ctrl+C鍵退出,只需要按R鍵進(jìn)行熱加載就可以使改動(dòng)生效,這意味著你不需要重新Build就可以修改你的App了。如果更新失敗或者模擬器卡住了,需要按Shift+R鍵重新Build才可以。接下來(lái)回到模擬器,單擊“加號(hào)浮動(dòng)”按鈕,會(huì)看到計(jì)數(shù)器每次增加2而不是1,這是第一個(gè)小的改變,接下來(lái)我們將更深入地學(xué)習(xí)Flutter。1.7Flutter中的MaterialDesign體系MaterialDesign是谷歌創(chuàng)建的一個(gè)設(shè)計(jì)系統(tǒng),它看起來(lái)如圖1.28所示。Flutter使用了MaterialDesign。它不僅是一種樣式,還可以靈活地自定義樣式,例如可以改變顏色、位置或者包含其他小部件,這樣就可以設(shè)計(jì)出自己的小部件。MaterialDesign已經(jīng)植入到Flutter中了,F(xiàn)lutter也依賴MaterialDesign,所以FlutterApp實(shí)際上也是MaterialApp。Flutter正在積極地快速發(fā)展,現(xiàn)在已經(jīng)有了很多穩(wěn)定版本,隨著版本的更新,功能也隨之更新。關(guān)注官網(wǎng)可以及時(shí)了解它的變化。同時(shí)也會(huì)有更多的第三方軟件包添加到Flutter的生態(tài)系統(tǒng)中。Flutter也可能會(huì)存在Bug,如果遇到Bug,可以先定位Bug,確定到底哪里出問(wèn)題了,然后關(guān)注這個(gè)問(wèn)題。圖1.28MaterialDesign與Flutter的關(guān)系第2章深入理解Flutter基礎(chǔ)知識(shí)和小部件概念本章將深入學(xué)習(xí)Flutter和Dart及使用Flutter構(gòu)建移動(dòng)App,還包括學(xué)習(xí)Flutter的核心基礎(chǔ)知識(shí),主要是關(guān)于小部件的。不僅在理論上學(xué)習(xí)Flutter,還將使用Flutter構(gòu)建項(xiàng)目。現(xiàn)在讓我們創(chuàng)建一個(gè)新的Flutter項(xiàng)目。2.1創(chuàng)建一個(gè)Flutter項(xiàng)目要?jiǎng)?chuàng)建一個(gè)Flutter項(xiàng)目,需要使用Flutter命令。首先需要配置Flutter的環(huán)境變量,在第1章已經(jīng)介紹了,然后在命令提示符中運(yùn)行命令fluttercreate加上項(xiàng)目名稱,如圖2.1所示,如果項(xiàng)目名稱涉及多個(gè)單詞,請(qǐng)使用下畫線分隔,而不可以使用橫線和空格,單擊回車鍵。這將在當(dāng)前運(yùn)行命令的目錄下創(chuàng)建一個(gè)新的目錄,所以要確認(rèn)好當(dāng)前的目錄。新創(chuàng)建的目錄中包含了大量Flutter自動(dòng)創(chuàng)建的Android和iOS相關(guān)文件。項(xiàng)目創(chuàng)建完成后,在日志中會(huì)顯示一些可以運(yùn)行的命令。現(xiàn)在不需要運(yùn)行它們,而是使用IDE打開(kāi)這個(gè)新創(chuàng)建的項(xiàng)目。圖2.1創(chuàng)建Flutter項(xiàng)目的命令這里使用VisualStudioCode打開(kāi)這個(gè)項(xiàng)目,也可以使用AndroidStudio打開(kāi)它。首先確保VisualStudioCode安裝了Flutter插件,然后打開(kāi)VisualStudioCode集成的終端,在View下選擇Terminal,如圖2.2所示。圖2.2打開(kāi)VisualStudioCode中的終端在當(dāng)前項(xiàng)目目錄下的Terminal中運(yùn)行Flutter命令,但是現(xiàn)在還啟動(dòng)不了,因?yàn)檫\(yùn)行Flutter項(xiàng)目需要一個(gè)模擬器或一個(gè)真實(shí)的設(shè)備。這里使用模擬器,所以讓我們快速啟動(dòng)一個(gè)模擬器,打開(kāi)AndroidStudio,單擊“Tools”按鈕,再單擊“AVDManager”按鈕,如圖2.3所示。圖2.3打開(kāi)VisualStudioCode中的終端選擇一個(gè)設(shè)備,也可以創(chuàng)建一個(gè)新的設(shè)備,并單擊右側(cè)的“?”運(yùn)行按鈕,如圖2.4所示。圖2.4啟動(dòng)Android模擬器模擬器運(yùn)行起來(lái)后,回到VisualStudioCode中,啟動(dòng)Flutter項(xiàng)目,單擊“Debug”按鈕,選擇“StartDebugging”,或者“StartWithoutDebugging”,如圖2.5所示。圖2.5啟動(dòng)Flutter項(xiàng)目此時(shí)模擬器有可能會(huì)提示選擇環(huán)境變量,只需選擇FlutterAndDart即可。構(gòu)建好Flutter項(xiàng)目后,IDE會(huì)發(fā)送給模擬器,如圖2.6所示。頂部有個(gè)控制面板,可以調(diào)試、重啟、退出、暫停項(xiàng)目。這個(gè)應(yīng)用程序如圖2.6中模擬器所示,這是Flutter自帶的,而不是我們編寫的,下一節(jié)我們將重新編寫一個(gè)應(yīng)用程序。圖2.6運(yùn)行的Flutter項(xiàng)目2.2Flutter目錄結(jié)構(gòu)及main文件我們啟動(dòng)并在模擬器上運(yùn)行了Flutter項(xiàng)目,現(xiàn)在打開(kāi)main.dart這個(gè)文件并刪除所有內(nèi)容,如圖2.7所示,從零開(kāi)始學(xué)習(xí)如何編寫Flutter代碼。首先介紹一下圖2.7中左側(cè)的目錄和文件:.idea目錄是AndroidStudio中的文件不要?jiǎng)h除,也不需要了解其中的內(nèi)容;android和ios目錄非常重要,因?yàn)樗鼈儽4嬷緳C(jī)的代碼,并且是應(yīng)用構(gòu)建過(guò)程的重要部分,android和ios目錄中的內(nèi)容不經(jīng)常用到,后面的章節(jié)用到時(shí)再學(xué)習(xí);lib目錄是編寫整個(gè)Flutter應(yīng)用的地方,我們將在這個(gè)目錄下編寫Dart和Flutter代碼;test目錄下可以編寫自動(dòng)化測(cè)試代碼。其他文件是基本的配置文件,例如.gitignore文件是版本控制文件,其他配置文件中包含SDK的配置信息,不需要編輯它們。pubspec.yaml文件是配置整個(gè)項(xiàng)目及其依賴的,這個(gè)文件是很重要的。后面章節(jié)會(huì)介紹添加第三方包,例如相機(jī)設(shè)備,會(huì)經(jīng)常修改這個(gè)文件中的某些配置,現(xiàn)在編寫我們應(yīng)用程序的一些基礎(chǔ)代碼。main.dart文件是一個(gè)很重要的文件,不可以重新命名,因?yàn)镕lutter構(gòu)建項(xiàng)目時(shí)會(huì)尋找main.dart這個(gè)文件,文件中包含一些特殊的方法來(lái)啟動(dòng)整個(gè)App,其中有一個(gè)main()方法,在Flutter中創(chuàng)建方法,需要輸入一個(gè)名字例如main,這個(gè)方法比較特殊,App在啟動(dòng)的時(shí)候會(huì)尋找這個(gè)main方法。其他的方法可以自己命名,然后輸入括號(hào),在括號(hào)中可以指定任何參數(shù),然后在方法體中使用這些數(shù)據(jù),但是main()方法不接受任何參數(shù),方法體中執(zhí)行的代碼需要用大括號(hào)括起來(lái)。如果執(zhí)行某個(gè)方法,可以像如下代碼這樣寫。圖2.7Flutter項(xiàng)目中的main.dart

main();//調(diào)用main()方法

但是對(duì)于main()這個(gè)特殊的方法我們不能去調(diào)用它,F(xiàn)lutter會(huì)自動(dòng)調(diào)用它,所以這就是我們必須要命名為main()并且把它放到main.dart中的原因。現(xiàn)在可以啟動(dòng)App,開(kāi)始渲染用戶界面并運(yùn)行到操作系統(tǒng)上,這可以通過(guò)Android和iOS來(lái)完成,但是要在屏幕上呈現(xiàn)一些內(nèi)容,需要在main()方法中做一些事情。例如將一個(gè)小部件附加到屏幕上,接下來(lái)講解什么是小部件。2.3Flutter中小部件的概念Flutter中一切都是小部件,小部件是構(gòu)造塊,UI組件。如果將一個(gè)Flutter應(yīng)用運(yùn)行到移動(dòng)設(shè)備上,它通常由多個(gè)小部件組成。例如頂部的標(biāo)題欄、導(dǎo)航欄、標(biāo)題圖片、包含內(nèi)容的列表等,它們都是單獨(dú)的小部件,通常還包含其他小部件,如圖2.8所示。圖2.8中的列表含列表項(xiàng)作為子部件。頁(yè)面本身也是小部件,如圖2.8所示的scaffold小部件,甚至整個(gè)應(yīng)用程序都包含在一個(gè)根小部件中。因此小部件實(shí)際上是UI組件,但它們不僅僅是視覺(jué)組件,還包含邏輯組件。例如,按鈕小部件不僅會(huì)顯示按鈕,還會(huì)定義單擊按鈕時(shí)會(huì)發(fā)生什么。構(gòu)建Flutter應(yīng)用程序是通過(guò)創(chuàng)建UI,然后編寫UI的邏輯來(lái)實(shí)現(xiàn)的,例如選擇移動(dòng)設(shè)備上的圖片并上傳到服務(wù)器上、從服務(wù)器上獲取數(shù)據(jù)并渲染到屏幕上等。圖2.8Flutter應(yīng)用中的小部件我們可以將Flutter應(yīng)用視為小部件的樹(shù),一個(gè)根小部件包含整個(gè)應(yīng)用程序,可能會(huì)有40個(gè)不同頁(yè)面的小部件作為子小部件,然后為子小部件嵌套其他小部件,如圖2.9所示。圖2.9Flutter中的小部件樹(shù)實(shí)際上我們建立了如圖2.9所示的一個(gè)小部件樹(shù),我們可以使用Dart編程語(yǔ)言完成所有這些工作,讓我們看看如何創(chuàng)建這樣的小部件樹(shù)。2.4創(chuàng)建Flutter小部件現(xiàn)在App中沒(méi)有任何內(nèi)容,我們只寫了一個(gè)main()方法,將來(lái)它將會(huì)被調(diào)用,但是我們不知道在main()方法里執(zhí)行什么。上一節(jié)我們學(xué)習(xí)到整個(gè)Flutter應(yīng)用都是由小部件組成的,所以我們應(yīng)該寫一個(gè)小部件。首先創(chuàng)建根小部件,要實(shí)現(xiàn)它需要使用Dart語(yǔ)言的一個(gè)特性——類。你可能在其他的語(yǔ)言中聽(tīng)說(shuō)過(guò)這個(gè)概念,Dart是面向?qū)ο蟮木幊陶Z(yǔ)言,所以一切都是對(duì)象,一個(gè)對(duì)象就是一個(gè)簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu),類允許為對(duì)象創(chuàng)建屬性和方法。Flutter提供了很多類供我們使用,但也可以創(chuàng)建自己的類。輸入class關(guān)鍵字后,可以輸入一個(gè)類名,類名以一個(gè)大寫字母開(kāi)頭,然后輸入名字,代碼如下:

classMyapp//class關(guān)鍵字加上類名

這里將Myapp作為一個(gè)詞使用,也可以使用多個(gè)詞,每個(gè)詞以大寫字母開(kāi)頭,代碼如下:

classMyApp//將MyApp作為多個(gè)詞來(lái)命名

類的名稱不能使用橫線、下畫線,這就是類?,F(xiàn)在可以給這個(gè)類加一些特性,例如方法、變量,變量你可能從其他的語(yǔ)言中了解過(guò),變量是簡(jiǎn)單的、小的數(shù)據(jù)結(jié)構(gòu),例如name='tom'。但是,如果想把一個(gè)混合的數(shù)據(jù)賦值給name,需要把name指向一個(gè)對(duì)象?,F(xiàn)在我們想創(chuàng)建一個(gè)小部件,一個(gè)小部件是一個(gè)對(duì)象,這個(gè)對(duì)象是由類來(lái)定義的,但是我們自己創(chuàng)建的類,F(xiàn)lutter不認(rèn)為它是一個(gè)小部件類,因?yàn)橐粋€(gè)小部件需要某些特性,因此我們的類必須繼承其他的類,繼承使用extends這個(gè)關(guān)鍵字,允許繼承一個(gè)類,意味著當(dāng)前類繼承了這個(gè)類的所有特性,然后你可以使用這些特性或者添加自己的特性。如果繼承了Flutter的類,F(xiàn)lutter便會(huì)知道它可以安全地使用這個(gè)類的對(duì)象,并在屏幕上繪制一些內(nèi)容。我們需要繼承的類來(lái)自Flutter框架,所以需要了解特性import。編寫代碼時(shí)需要使用FlutterSDK框架中的代碼,因此需要通過(guò)import關(guān)鍵字,引入需要的文件的路徑,從這些特性可看出Dart是一門模塊化的語(yǔ)言,同時(shí)也意味著可以將代碼切分成多個(gè)文件,下面引入Flutter包中的文件,代碼如下:

import'package:flutter/material.dart';//引入Flutter框架中的文件

我們通過(guò)package:加包名flutter,flutter包中包括很多的子包或者文件,可以通過(guò)/加文件名來(lái)定位文件,上述例子中引入了material.dart這個(gè)文件。現(xiàn)在我們可以繼承這個(gè)文件中暴露的一些類。例如無(wú)狀態(tài)小部件StatelessWidget、有狀態(tài)的小部件StatefulWidget。因?yàn)槲覀円肓藢?duì)應(yīng)的文件,所以這里繼承StatelessWidget,代碼如下:

//Chapter02/02-04/lib/main.dart

classMyappextendsStatelessWidget{//繼承無(wú)狀態(tài)小部件

}

現(xiàn)在就可以把它作為一個(gè)小部件并顯示在屏幕上了。這里還有一個(gè)很重要的事情需要說(shuō)明,將在下一節(jié)介紹。2.5小部件中的build方法現(xiàn)在Myapp類已經(jīng)繼承了StatelessWidget,因此Myapp是一個(gè)有效的小部件了,我們可以看到Myapp下面有一個(gè)橫線,如果把鼠標(biāo)懸停在上面,會(huì)看見(jiàn)一些錯(cuò)誤的提示信息,如圖2.10所示。圖2.10Myapp中錯(cuò)誤的提示信息提示當(dāng)前類中缺少build方法,所以輸入build()加上大括號(hào),定義一個(gè)方法。但還是有下畫線,如圖2.11所示。圖2.11build方法提示的錯(cuò)誤信息這里需要告訴Flutter,Myapp這個(gè)類創(chuàng)建的對(duì)象是一個(gè)小部件,需要顯示到屏幕上,也可以認(rèn)為Flutter通過(guò)調(diào)用對(duì)象中的build()方法來(lái)顯示某些內(nèi)容,這就是要在創(chuàng)建小部件中添加build()方法的原因。build()方法實(shí)際上需要通過(guò)方法中的參數(shù)傳遞一些數(shù)據(jù),這些數(shù)據(jù)是Flutter傳遞的。因?yàn)镕lutter會(huì)調(diào)用build()方法,build()方法需要一個(gè)參數(shù)context,context實(shí)際上是一個(gè)對(duì)象,包含應(yīng)用的一些元信息,以及繪制小部件的位置。例如context中包含了應(yīng)用的主題,目前可以先忽略它?,F(xiàn)在我們?cè)赽uild()方法中添加一些內(nèi)容。build()方法需要返回內(nèi)容,所以需要使用return關(guān)鍵字。因?yàn)镕lutter需要執(zhí)行build()方法來(lái)知道在屏幕上繪制什么,所以Flutter需要執(zhí)行build()方法返回的內(nèi)容,我們?cè)诜椒w中添加return關(guān)鍵字,但現(xiàn)在的問(wèn)題是需要在這里返回什么。這里有一個(gè)很重要的規(guī)則,在build()方法中,小部件總會(huì)返回另一個(gè)小部件,一直遞歸到Flutter附帶的小部件為止。這里可以使用Flutter附帶的MaterialApp小部件,它是一個(gè)很特殊的小部件,可以用來(lái)包裝整個(gè)App。App可以通過(guò)它來(lái)設(shè)置主題,也可以添加一個(gè)導(dǎo)航器,使應(yīng)用在不同頁(yè)面間進(jìn)行切換等。所以MaterialApp是核心的根小部件,在每個(gè)FlutterApp中都會(huì)用到它。在Myapp小部件中將MaterialApp返回,作為最頂級(jí)的小部件,代碼如下:MaterialApp小部件中可以配置一些內(nèi)容,并顯示在屏幕上。現(xiàn)在模擬器上面沒(méi)有顯示任何內(nèi)容,所以需要給MaterialApp傳遞數(shù)據(jù),下一節(jié)來(lái)實(shí)現(xiàn)這個(gè)功能。2.6添加Scaffold頁(yè)面到目前為止,F(xiàn)lutter的內(nèi)容已經(jīng)涵蓋了很多方面,但是在模擬器的屏幕上還是什么都看不到,所以我們需要告訴MaterialApp需要做些什么,然后顯示到模擬器的屏幕上。我們可以給MaterialApp傳遞參數(shù)。之前在創(chuàng)建build()方法時(shí)需要一個(gè)參數(shù),同樣MaterialApp的構(gòu)造器也需要傳遞參數(shù),它接收命名的參數(shù),這意味需要添加一個(gè)名字,例如home。這個(gè)參數(shù)加上冒號(hào)然后加上傳遞的值,還有一種是位置參數(shù),例如build(context),這里的參數(shù)不需要名字,build()方法中傳遞的第一個(gè)參數(shù)會(huì)被認(rèn)為是context。在Flutter中我們會(huì)經(jīng)常用到命名參數(shù)?,F(xiàn)在我們需要給home這個(gè)參數(shù)傳遞一個(gè)值,home需要傳遞的實(shí)際上是小部件,它們會(huì)被繪制到屏幕上。這里你可以使用Scaffold,它是material包附帶的,Scaffold可以在App中創(chuàng)建一個(gè)頁(yè)面,默認(rèn)是白色的背景,也可以修改這個(gè)背景顏色。Scaffold還可以添加標(biāo)題欄等小部件。同樣需要在構(gòu)造器中傳遞數(shù)據(jù),其中一個(gè)參數(shù)叫appBar,輸入冒號(hào),添加一個(gè)頂部的導(dǎo)航欄AppBar()小部件,現(xiàn)在同樣也需要配置AppBar來(lái)顯示內(nèi)容。其中一個(gè)參數(shù)為title。把鼠標(biāo)懸停在AppBar上,會(huì)看到我們可以傳遞哪些參數(shù),你會(huì)發(fā)現(xiàn)title這個(gè)參數(shù)同樣會(huì)傳遞一個(gè)小部件。這里我會(huì)用到這個(gè)小部件鏈上的最后一個(gè)小部件Text,Text是一個(gè)需要傳遞String類型數(shù)據(jù)的小部件。Text是由位置參數(shù)創(chuàng)建的,所以只需要傳遞一個(gè)String類型的數(shù)據(jù),并放在參數(shù)的第一個(gè)位置,代碼如下:這樣Text小部件就可以獲取到數(shù)據(jù)了。現(xiàn)在傳遞一個(gè)String類型的數(shù)據(jù),它將會(huì)被顯示出來(lái)。但是在模擬器的屏幕上還是什么都看不到,這是因?yàn)殡m然我們創(chuàng)建了小部件,但沒(méi)有掛載到屏幕上。在main()方法中,沒(méi)有執(zhí)行任何內(nèi)容。main()方法中需要運(yùn)行一個(gè)特殊的方法,也是material包附帶的,這個(gè)特殊方法是runApp()。runApp()方法需要傳遞一個(gè)參數(shù),這個(gè)參數(shù)必須是一個(gè)小部件。創(chuàng)建小部件Myapp,代碼如下:Myapp中包含了MaterialApp、Scaffold等。可以嘗試使用熱加載運(yùn)行模擬器,如果失敗了,需要退出,然后單擊“StartWithoutDebugging”來(lái)啟動(dòng)。這就是當(dāng)前我們的App,如圖2.12所示。圖2.12成功啟動(dòng)Flutter應(yīng)用可以看到AppBar和Scaffold的白色背景,以及包含這一切的MaterialApp的小部件。2.7深入學(xué)習(xí)Dart語(yǔ)法我們創(chuàng)建了一個(gè)非常簡(jiǎn)單的Flutter應(yīng)用,在main.dart文件中調(diào)用main()方法,然后調(diào)用runApp()方法,在runApp()方法中創(chuàng)建了一個(gè)我們自己的類的對(duì)象,實(shí)際上是調(diào)用Flutter的build()方法返回了一個(gè)小部件樹(shù)。我們用Dart語(yǔ)言編寫了以上內(nèi)容,例如導(dǎo)入語(yǔ)句、方法的語(yǔ)法、類等,這些都是用Dart編寫的。Dart實(shí)際上是一種強(qiáng)類型語(yǔ)言,意味著必須定義方法和變量的類型。這對(duì)開(kāi)發(fā)者來(lái)說(shuō)是有幫助的,因?yàn)槿绻爿斎胍粋€(gè)錯(cuò)誤的類型,IDE會(huì)有錯(cuò)誤的提示信息,在構(gòu)建應(yīng)用過(guò)程中也會(huì)被發(fā)現(xiàn)。build()方法返回了一個(gè)小部件,但是我們并沒(méi)有聲明返回類型,不過(guò)IDE也沒(méi)提示報(bào)錯(cuò)。這是因?yàn)镈art語(yǔ)言實(shí)際上已經(jīng)根據(jù)MaterialApp小部件推測(cè)出會(huì)返回一個(gè)小部件。為了使這段代碼更清晰,我們需要在build()方法前面加Widget這個(gè)類型,意味著Widget是我們期望的返回類型。如果把return返回的內(nèi)容設(shè)置為'hello',IDE會(huì)給我們錯(cuò)誤的提示信息,顯示返回類型錯(cuò)誤。這樣當(dāng)保存代碼的時(shí)候,代碼不能被重新編譯。所以在build()方法前,要改成返回一個(gè)小部件。代碼如下:添加返回類型可以避免出現(xiàn)錯(cuò)誤。build()方法實(shí)際上是StatelessWidget中一個(gè)已經(jīng)定義的方法,我們可以在build()方法的參數(shù)前面加一個(gè)類型,使代碼更清晰,參數(shù)context的類型是BuildContext,BuildContext是material包中提供的另外一個(gè)類,代碼如下:這樣我們可以很清楚地知道context是BuildContext的類型,確保我們?cè)谑褂脮r(shí)不會(huì)犯錯(cuò)。對(duì)IDE來(lái)說(shuō)也很好,在IDE中我們可以通過(guò)context加點(diǎn)來(lái)獲得提示和建議。我們也可以給main()方法加返回類型,main()方法沒(méi)有返回任何內(nèi)容,可以在前面加void類型,表示這個(gè)方法不會(huì)返回任何內(nèi)容,代碼如下:如果有返回值,IDE會(huì)提示報(bào)錯(cuò)。現(xiàn)在的代碼比之前更易讀了,所以強(qiáng)烈建議使用類型,類型是一個(gè)關(guān)鍵的特性,將在后面章節(jié)中經(jīng)常使用它。如果main()方法中只有一行代碼,有一個(gè)更簡(jiǎn)單的寫法,代碼如下:build()方法實(shí)際上是StatelessWidget類中的方法,我們覆蓋了它,所以我們需要在這里加一個(gè)注解,代碼如下:添加@override注解不是必須的,@override可以告訴Dart和Flutter,我們有意重寫這個(gè)方法。加注解可以使代碼變得好理解?,F(xiàn)在代碼變得更清晰了,下一節(jié)我們給這個(gè)應(yīng)用加些其他的內(nèi)容。2.8使用Card小部件和圖片現(xiàn)在應(yīng)用中只有一個(gè)導(dǎo)航欄,Scaffold是用來(lái)創(chuàng)建頁(yè)面的,不僅可以在它上面創(chuàng)建AppBar,還可以添加其他參數(shù),把鼠標(biāo)懸停在Scaffold上,會(huì)看到有一個(gè)參數(shù)body,如圖2.13所示。圖2.13Scaffold中的參數(shù)bodybody顯示在appBar的下面,它也需要傳遞一個(gè)小部件。在body:后面創(chuàng)建一個(gè)Flutter的小部件,也可以是自定義的小部件。自定義的小部件會(huì)形成Flutter附帶的小部件樹(shù),但最終也會(huì)遞歸成Flutter附帶的小部件,這是因?yàn)橹挥蠪lutter附帶的小部件才能被轉(zhuǎn)化為原生的UI組件。在body里添加一個(gè)Card小部件,它也是flutter/material包中附帶的。Card中的內(nèi)容突出顯示,還略帶陰影效果。同樣它也需要傳遞一些參數(shù),其中一個(gè)重要的參數(shù)是child,child同樣也需要傳遞一個(gè)小部件。傳遞的小部件就是顯示在卡片上的內(nèi)容。我們?cè)诳ㄆ霞訄D片和圖片下面的標(biāo)題這兩個(gè)元素,這里需要傳入另外一個(gè)小部件,它也是Flutter附帶的,即Column小部件。它同樣需要傳入?yún)?shù),其中一個(gè)參數(shù)叫children,和child不同,child只需傳一個(gè)小部件,children需要傳入多個(gè)小部件并上下排列。代碼如下:用<>括起來(lái)的寫法叫泛型,是數(shù)組的一個(gè)附加注解,使我們更清楚地知道這個(gè)數(shù)組只能包含小部件。[]括起來(lái)的是數(shù)組,可以傳入一組數(shù)據(jù)而不僅僅是一個(gè)數(shù)據(jù),例如Column、Card、AppBar、Text、Scaffold等。這里可以添加兩個(gè)小部件,以逗號(hào)分隔。一個(gè)是小部件Image,它也是包flutter/material附帶的;另一個(gè)是Text小部件,并傳入一個(gè)字符串'news1'。代碼如下:Image需要傳入一張圖片,在項(xiàng)目中創(chuàng)建一個(gè)目錄,命名為assets,用它來(lái)保存靜態(tài)資源。我們可以任意找一張圖片,并重命名為news1.jpg,然后把它拖放到assets這個(gè)目錄下。要顯示這張圖片,把它放到這個(gè)目錄下還不夠,我們需要在pubspec.yaml這個(gè)文件中配置訪問(wèn)圖片的路徑。訪問(wèn)的文件是assets下面的news1.jpg,如圖2.14所示?,F(xiàn)在就可以在項(xiàng)目中使用這張圖片了。在main.dart中,可以使用Image小部件特別的構(gòu)造器來(lái)創(chuàng)建,Image小部件和括號(hào)之間加.asset,代碼如下:Image將加載已經(jīng)配置好的資源,參數(shù)是資源的路徑,類型是String。保存后,圖片將會(huì)被加載到App上,如圖2.15所示。圖片和圖片下面的標(biāo)題分布在Card上面,占據(jù)了整個(gè)Card的寬和高,可以看到底部略帶陰影,但是我們希望構(gòu)建更多的內(nèi)容來(lái)形成小部件樹(shù)。接下來(lái)我們學(xué)習(xí)更多的核心小部件。圖2.14配置圖片路徑圖2.15圖片在App上顯示的效果2.9官方文檔及使用按鈕RaisedButtonFlutter官網(wǎng)上提供了很多內(nèi)容,用瀏覽器訪問(wèn)flutter.dev,單擊“Getstarted”按鈕,如圖2.16所示。圖2.16Flutter官網(wǎng)在左側(cè)找到Widgetcatalog,單擊此鏈接,如圖2.17所示,可以看到Flutter自帶的所有小部件,而且它們被分類了。圖2.17Flutter中的小部件最重要的一個(gè)分類是Basics小部件,還有一個(gè)很重的分類是MaterialComponents小部件。MaterialComponents中包含AppBar、按鈕、輸入框、對(duì)話框、Card等。Basics小部件包含行、列、Container、Text、Image小部件,可以單擊小部件上的鏈接了解更多的內(nèi)容,例如小部件的構(gòu)造器,有的還有一些關(guān)于小部件的示例代碼。這些小部件看起來(lái)很多,不用擔(dān)心,我們將在本書中使用大量的小部件,一切都會(huì)變得更加清晰。知道怎么找到這些小部件了,現(xiàn)在可以繼續(xù)豐富App的功能了。當(dāng)前的App只是顯示了Card,它占據(jù)了整個(gè)空間,這種效果并不是我們想要的。現(xiàn)在修改它,添加更多的Card來(lái)展示一列Card??梢允褂肅olumn小部件,并給參數(shù)children傳值,然后把Card添加到數(shù)組[]中,代碼如下:重啟后會(huì)發(fā)現(xiàn)Card底部有一個(gè)邊了,如圖2.18所示。圖2.18Card顯示在列中現(xiàn)在可以加更多的Card了。同時(shí)需要在Card所在的列上面添加一個(gè)按鈕,可以添加RaisedButton小部件。它是一個(gè)帶有背景的按鈕,按鈕也需要配置一下,最重要的一個(gè)參數(shù)是child,它用來(lái)定義這個(gè)按鈕內(nèi)部顯示,可以傳入Text小部件,也可以傳入一個(gè)圖標(biāo)。這里使用Text,Text的內(nèi)容是'添加資訊'。這里還需要傳入另外一個(gè)參數(shù)onPressed。值應(yīng)該是一個(gè)方法,所以這里可以簡(jiǎn)單定義一個(gè)空的方法,這個(gè)叫匿名方法,沒(méi)有名稱,只有參數(shù)列表和方法體?,F(xiàn)在都是空的,所以單擊按鈕不會(huì)執(zhí)行任何內(nèi)容。代碼如下:保存并重新加載,會(huì)發(fā)現(xiàn)屏幕頂部有一個(gè)按鈕可以單擊,但沒(méi)有任何反應(yīng)。這個(gè)按鈕顯示得并不美觀,可以用Container小部件把它包裝起來(lái)。Container小部件中child參數(shù)的值就是按鈕。Container小部件有一個(gè)參數(shù)叫margin,表示Container與四周的外邊距。margin參數(shù)可以使用flutter/material包中的類EdgeInsets來(lái)賦值,這個(gè)類可以使用.all來(lái)調(diào)用構(gòu)造器,傳入一個(gè)浮點(diǎn)類型來(lái)定義四周邊界的距離,例如10.0像素。代碼如下:這個(gè)像素會(huì)自動(dòng)適配設(shè)備的像素,現(xiàn)在我們可以看見(jiàn)按鈕周圍產(chǎn)生了邊距,但這個(gè)按鈕沒(méi)有任何功能,下一節(jié)讓我們將給這個(gè)按鈕加些功能!2.10創(chuàng)建StatefulWidget小部件現(xiàn)在單擊應(yīng)用中的按鈕沒(méi)有任何反應(yīng),因?yàn)楸O(jiān)聽(tīng)方法是空的,這個(gè)按鈕應(yīng)該具有添加更多Card小部件的功能。那么怎樣再添加更多的Card呢?還有個(gè)問(wèn)題是怎樣通過(guò)單擊按鈕來(lái)添加Card小部件呢?在按鈕的監(jiān)聽(tīng)方法中,我們想改變一些數(shù)據(jù),然后動(dòng)態(tài)地添加到卡片的列表中。我們需要管理一組數(shù)據(jù),例如從服務(wù)器獲得的數(shù)據(jù),后邊的章節(jié)將會(huì)介紹。首先確認(rèn)build()方法什么時(shí)候被調(diào)用,build()方法會(huì)在應(yīng)用第一次加載的時(shí)候被Flutter調(diào)用,或者當(dāng)數(shù)據(jù)發(fā)生改變的時(shí)候也會(huì)被調(diào)用。可以在onPressed監(jiān)聽(tīng)的方法中管理這組數(shù)據(jù),每次單擊按鈕時(shí)都要改變這組Card。StatelessWidget滿足不了這個(gè)需求,因?yàn)樗且粋€(gè)很簡(jiǎn)單的小部件,StatelessWidget可以接收外部的數(shù)據(jù),然后簡(jiǎn)單地調(diào)用build()方法,構(gòu)建一個(gè)小部件樹(shù),它沒(méi)辦法管理內(nèi)部數(shù)據(jù)。如果內(nèi)部數(shù)據(jù)發(fā)生變化,也不能重新調(diào)用build()方法,因?yàn)镾tatelessWidget不能管理內(nèi)部數(shù)據(jù)。StatelessWidget只能在第一次被創(chuàng)建的時(shí)候調(diào)用build()方法,或者是接收到某些外部數(shù)據(jù)發(fā)生變化時(shí),它會(huì)調(diào)用build()方法,所以現(xiàn)在不能使用StatelessWidget。我們需要使用StatefulWidget,State可以被簡(jiǎn)單地理解為數(shù)據(jù),可以使用存儲(chǔ)在小部件中的數(shù)據(jù),同時(shí)也可以改變這些數(shù)據(jù)。當(dāng)我們改成StatefulWidget后會(huì)有一個(gè)錯(cuò)誤提示,顯示缺少方法createState(),如圖2.19所示。圖2.19缺少方法createState()createState()方法是必須要?jiǎng)?chuàng)建的,現(xiàn)在我們把這個(gè)類用大括號(hào)結(jié)束,代碼如下:在Myapp類中輸入createState()方法,VisualStudioCode會(huì)給提示,單擊回車鍵,代碼如下:createState()方法返回一個(gè)有狀態(tài)的小部件對(duì)象,<>是泛型,State這個(gè)類是屬于flutter/material包。這個(gè)狀態(tài)對(duì)象應(yīng)該屬于Myapp。實(shí)際上需要?jiǎng)?chuàng)建兩個(gè)類來(lái)一起工作,createState()方法需要返回一個(gè)新的State對(duì)象,然后把這個(gè)對(duì)象配置給Myapp。還需要?jiǎng)?chuàng)建第二個(gè)類,可以寫成_MyappState,類名中的下畫線是一種約定,表示它不能被其他文件使用,只能在這個(gè)文件中使用。后面的內(nèi)容可能會(huì)使用多個(gè)文件,可以把Myapp引入到文件中并使用它,但是不可以使用_MyappState,然后輸入extends,因?yàn)镾tate這個(gè)對(duì)象是屬于Flutter的,需要覆蓋build()方法,這是因?yàn)镾tate這個(gè)類中也有build()方法?,F(xiàn)在我們只需要告訴Flutter,這個(gè)狀態(tài)類是屬于Myapp這個(gè)小部件的,需要在<>中加上Myapp,表明這個(gè)State屬于誰(shuí),這樣這兩個(gè)類的關(guān)系就創(chuàng)建起來(lái)了。Myapp需要返回_MyappState對(duì)象,所以把_MyappState()返回。代碼如下:類Myapp創(chuàng)建了一個(gè)State對(duì)象,這個(gè)對(duì)象包含build()方法,F(xiàn)lutter內(nèi)部會(huì)調(diào)用build()方法,這就是StatefulWidget的使用方法。那么怎么去使用StatefulWidget改變這組Card呢?下一節(jié)我們將詳細(xì)講解。2.11在StatefulWidget中管理數(shù)據(jù)我們已經(jīng)創(chuàng)建了一個(gè)StatefulWidget小部件,但問(wèn)題是怎樣去管理和改變它內(nèi)部的數(shù)據(jù),可以用一個(gè)很簡(jiǎn)單的方式去實(shí)現(xiàn)它。在_MyappState中添加一個(gè)屬性news,代碼如下:news是一個(gè)String類型的數(shù)組,因?yàn)镈art是強(qiáng)類型語(yǔ)言,所以需要在news的前面加類型List,這是Dart中的類型,表示數(shù)組。List可以添加泛型,這里是String泛型,表示這個(gè)數(shù)組中的內(nèi)容都是String類型的,這就是_MyappState的屬性。但數(shù)組是空的,下面我們給數(shù)組賦值,在中括號(hào)中輸入第一條資訊'first',代碼如下:現(xiàn)在需要把數(shù)組轉(zhuǎn)換到Card列表中并渲染到屏幕上,使用屬性時(shí)不可以使用this,可以直接引用它。這里需要調(diào)用數(shù)組的一個(gè)方法,在news后加點(diǎn),有一個(gè)叫map()的方法,它允許將列表中的每一個(gè)元素轉(zhuǎn)換為新元素并將其返回。我們將在Column中的children參數(shù)列表返回一個(gè)新值,map中需要傳入一個(gè)方法參數(shù)來(lái)編寫轉(zhuǎn)化邏輯,方法將接收一個(gè)元素,這里你可以使用等號(hào)加箭頭來(lái)定義每個(gè)元素都發(fā)生了什么,代碼如下:我們需要根據(jù)元素創(chuàng)建Card,所以遍歷news中的每一個(gè)元素,然后把它轉(zhuǎn)化成Card。把Text小部件中的內(nèi)容直接替換成被遍歷的元素,因?yàn)樗鼈兌际荢tring類型的數(shù)據(jù)。有一點(diǎn)需要注意,需要把被遍歷的元素element用小括號(hào)括起來(lái),因?yàn)樗且粋€(gè)參數(shù),因?yàn)橹挥幸痪浯a,所以我們可以用=>這種方式編寫。雖然跨越了幾行代碼也是一句代碼。map()方法遍歷后返回的是一個(gè)Iterable類型的數(shù)據(jù),但是Column需要的是小部件數(shù)組,所以需要把map()方法遍歷后的結(jié)果轉(zhuǎn)化成List類型,我們可以通過(guò)調(diào)用tolist()方法來(lái)實(shí)現(xiàn)。下一節(jié)我們將學(xué)習(xí)使用按鈕添加更多的Card。2.12在StatefulWidget小部件中添加數(shù)據(jù)觸發(fā)按鈕的單擊事件能做一些事情,這里單擊按鈕需要改變news這個(gè)列表數(shù)據(jù)。當(dāng)數(shù)據(jù)發(fā)生變化時(shí),build()方法將會(huì)再次被執(zhí)行,此時(shí)它將使用的是更新后的news數(shù)組列表,進(jìn)而更新Card并渲染到屏幕上。理論上,如果增加news數(shù)組列表中的數(shù)據(jù),將會(huì)獲得更多的Card,所以在按鈕單擊事件這里可以給news數(shù)組列表添加新的值。因?yàn)閚ews數(shù)組列表是一個(gè)字符串列表,所以可以添加一個(gè)新的字符串'second',代碼如下:保存后,單擊按鈕卻什么都沒(méi)有發(fā)生。實(shí)際上我們改變了news,可以在這里打印出來(lái),代碼如下:這只是一個(gè)debug方法,VisualStudioCode在底部的控制臺(tái)會(huì)打印出日志,單擊按鈕,控制臺(tái)已經(jīng)打印出來(lái)first和second了,如圖2.20所示。圖2.20打印news數(shù)組但是我們只看見(jiàn)一個(gè)Card,這是因?yàn)槲覀冊(cè)谶@里改變了數(shù)據(jù),但是Flutter識(shí)別不出來(lái),默認(rèn)Flutter只關(guān)注屬性這里的數(shù)據(jù),當(dāng)屬性數(shù)據(jù)發(fā)生變化時(shí),必須告訴Flutter在StatefulWidget中已改變了屬性數(shù)據(jù)。要實(shí)現(xiàn)這樣的效果需要調(diào)用一個(gè)特殊的方法setState(),它是Flutter包提供的,需要接收一個(gè)方法參數(shù),在這個(gè)方法中編寫改變數(shù)據(jù)的方法,然后重新渲染App。這里添加news的數(shù)據(jù),代碼如下:保存一下,單擊按鈕會(huì)看到第二個(gè)卡片出現(xiàn)了。下一節(jié)我們?cè)賱?chuàng)建一個(gè)StatelessWidget,看看小部件之間如何交互。2.13把小部件拆分到單獨(dú)的文件中我們已經(jīng)學(xué)習(xí)了很多基礎(chǔ)的小部件,那么怎樣建立小部件之間的聯(lián)系呢?在編寫Flutter應(yīng)用的過(guò)程中,需要經(jīng)常做的一件事就是拆分代碼并封裝。不可以把所有的代碼都放在一個(gè)根的小部件中,就像Myapp這個(gè)StatefulWidget小部件一樣。我們可以把應(yīng)用拆分成多個(gè)細(xì)粒度的小部件,并把它們分發(fā)到多個(gè)文件中,這樣可以使每個(gè)小部件和文件都易讀,也容易維護(hù)。怎樣拆分呢?我們使用StatefulWidget來(lái)管理Card小部件和news數(shù)組,如果仔細(xì)觀察可以看到StatefulWidget是從這個(gè)列小部件開(kāi)始渲染Card的,其他的小部件如MaterialApp、Scaffold、AppBar還有RaisedButton,它們都不會(huì)改變。RaisedButton按鈕是觸發(fā)改變狀態(tài)的部分,但也可以把這個(gè)按鈕拆分出來(lái)。首先我們把Card列表拆分出來(lái)。創(chuàng)建一個(gè)新的文件,命名為news.dart,可以隨意命名,但按照慣例文件名全部小寫,如果有多個(gè)單詞的話,用下畫線分隔。文件格式是dart。在這個(gè)文件中渲染資訊列表,可以把Card列表所在的列小部件復(fù)制到news.dart文件中。在news.dart文件中創(chuàng)建一個(gè)類News?,F(xiàn)在需要擴(kuò)展來(lái)自Flutter中的類,我們需要在每一個(gè)文件中添加import,代碼如下所示:

import'package:flutter/material.dart';//引入material包

因?yàn)槊恳粋€(gè)文件都是獨(dú)立的。在main.dart中引入的material包不會(huì)在這里生效,所以這里需要引入flutter/material包,然后創(chuàng)建一個(gè)小部件,并復(fù)制Column的邏輯放到這個(gè)小部件中,現(xiàn)在的問(wèn)題是這里需要繼承一個(gè)有狀態(tài)的小部件還是無(wú)狀態(tài)的小部件呢??jī)煞N方式都可以,但最好在這里使用無(wú)狀態(tài)的小部件,這列Card是需要改變的,為什么使用無(wú)狀態(tài)的小部件呢?因?yàn)閿?shù)據(jù)的變化實(shí)際上是發(fā)生在其他的地方。News小部件接收一組news數(shù)據(jù),這組news數(shù)據(jù)可能被改變,但是它是在我們創(chuàng)建的News小部件之外被改變的。在News小部件中添加一個(gè)build()方法,使用VisualStudioCode的提示創(chuàng)建,代碼如下:把復(fù)制Column的邏輯放到return后面,代碼如下:IDE提示這個(gè)news不存在,怎樣把news數(shù)組傳到News這個(gè)小部件中呢?可以從外部傳入數(shù)據(jù),然后就可以在News小部件中使用傳入的數(shù)據(jù)了。我們可以通過(guò)構(gòu)造器來(lái)實(shí)現(xiàn),創(chuàng)建一個(gè)構(gòu)造器,輸入類名,小括號(hào),大括號(hào),代碼如下:構(gòu)造器在小部件創(chuàng)建的時(shí)候就會(huì)被調(diào)用,構(gòu)造器還有其他的特性,現(xiàn)在用到的一個(gè)特性是接收數(shù)據(jù)news數(shù)組,再可以給構(gòu)造器命名一個(gè)參數(shù)news,參數(shù)名可以任意命名,然后把傳進(jìn)來(lái)的news存儲(chǔ)到News類的屬性中,所以需要在類中添加一個(gè)屬性,代碼如下:news屬性的類型是字符串型的數(shù)組,它不能改變,也沒(méi)有初始化?,F(xiàn)在把構(gòu)造器中的news存儲(chǔ)到這個(gè)屬性news當(dāng)中。Dart語(yǔ)言提供了一個(gè)方便的快捷方式,在這里輸入this.news,會(huì)自動(dòng)獲取傳入的參數(shù),并將其存儲(chǔ)在具有相同名稱的屬性中,這里需要在構(gòu)造器后面加分號(hào),代碼如下:這樣就可以通過(guò)構(gòu)造器將數(shù)據(jù)傳遞到屬性中了。類News下面有一個(gè)波浪線,提示類中的所有內(nèi)容都是不可變的,如圖2.21所示。因?yàn)閯?chuàng)建的是StatelessWidget,無(wú)論怎樣它都不能對(duì)變化做出反應(yīng),所以必須標(biāo)注屬性不可以改變,在屬性前面加一個(gè)特殊的關(guān)鍵字final,代碼如下:圖2.21類News的提示信息這是Dart的一個(gè)特性,它告訴Flutter屬性news將永遠(yuǎn)不會(huì)改變。從構(gòu)造器獲得的值初始化后屬性news將永遠(yuǎn)不會(huì)改變。也可以不加這個(gè)final,加上它是為了更清楚這是一個(gè)僅從外部設(shè)置的值,如果有新的值從外部傳進(jìn)來(lái),它只是簡(jiǎn)單地替換之前的值,只是替換,不會(huì)改變,然后再使用替換的這個(gè)值調(diào)用build()方法。2.14使用自定義小部件在main.dart文件中,已經(jīng)刪除了渲染Card的代碼,再刪除Container中的按鈕,并將其放入到自己創(chuàng)建的小部件中。創(chuàng)建一個(gè)新的文件news_manager.dart,用它管理News小部件。首先引入flutter/material包,創(chuàng)建類NewsManager繼承StatefulWidget,因?yàn)樵贜ewsManager中需要管理news數(shù)據(jù)。StatefulWidget需要?jiǎng)?chuàng)建createState()方法,我們可以通過(guò)IDE的提示來(lái)創(chuàng)建,同時(shí)需要添加第二類_NewsManagerState繼承State,泛型連接到NewsManager,并且在_NewsManagerState中需要?jiǎng)?chuàng)建build()方法,在build()方法中需要返回的是按鈕和Card列表。代碼如下:現(xiàn)在缺少News小部件,需要在按鈕下面顯示News小部件。所以build()方法需要返回一個(gè)Column,并給參數(shù)children賦值,其中一個(gè)是包裝按鈕的小部件Container,另一個(gè)是在2.13節(jié)中的News小部件?,F(xiàn)在不可用,因?yàn)檫€沒(méi)有引入,引入News小部件的代碼如下:點(diǎn)代表當(dāng)前目錄,點(diǎn)點(diǎn)代表上一級(jí)目錄,這里只是在當(dāng)前目錄,所以使用./news.dart。下面就可以使用News小部件了,News需要傳入一個(gè)參數(shù),所以把news數(shù)組傳入。代碼如下:通過(guò)setState改變news數(shù)據(jù),并再次調(diào)用build()方法渲染,同時(shí)也會(huì)渲染這里的News小部件,它被傳入了更新后的news數(shù)組列表,這將導(dǎo)致在News小部件中再次調(diào)用build()方法,這就是我們的NewsManager小部件。下面在main.dart文件中使用NewsManager小部件。在main.dart中我們不需要處理任何狀態(tài),所以可以把StatefulWidget改成StatelessWidget,刪除createState()方法,只需要覆蓋build()方法,body中不再是一個(gè)Column,而是NewsManager小部件,所以引入news_manager.dart,代碼如下:創(chuàng)建一個(gè)NewsManager小部件對(duì)象,代碼如下:現(xiàn)在應(yīng)用代碼的結(jié)構(gòu)更清晰,包含多個(gè)文件,多個(gè)小部件,并且小部件可以復(fù)用,也使代碼更容易管理,因?yàn)槊恳粋€(gè)文件的內(nèi)容都不多,而且容易理解。2.15給StatefulWidget傳

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論