接觸Flutter有幾天了靶累,總覺得該寫點(diǎn)什么顾患,在寫的過程中暇检,發(fā)現(xiàn)自己更懂了一點(diǎn)Flutter。
用Android studio新建一個(gè)Flutter項(xiàng)目深寥,有三處會出現(xiàn)Material:
(1)main.dart第一行攘乒,import 'package:flutter/material.dart';
(2)main.dart第11行return MaterialApp?
(3)pubspec.yaml第45行uses-material-design: true
有幾個(gè)疑問:
1.material是什么?material.dart是什么惋鹅?material-design是什么则酝?
從https://flutterchina.club/網(wǎng)站上有一句原話如下:
使用Flutter內(nèi)置美麗的Material Design和Cupertino(iOS風(fēng)格)widget、豐富的motion API闰集、平滑而自然的滑動效果和平臺感知沽讹,為您的用戶帶來全新體驗(yàn)般卑。
可以看出,所有Material相關(guān)的可能都是一個(gè)東西爽雄,那就是一套叫Material的開發(fā)組件蝠检。再說直白一點(diǎn),就是一個(gè)官方已經(jīng)寫好的一個(gè)類庫挚瘟,material.dart里面包含的就是所有對外開放類庫的頭文件叹谁。這個(gè)時(shí)候應(yīng)該打開默認(rèn)創(chuàng)建的Flutter項(xiàng)目,按住command鍵+鼠標(biāo)左鍵刽沾,看下material.dart的具體內(nèi)容。
那么uses-material-design: true這句話就很好理解了?試想:如果要使用Material的開發(fā)組件排拷,則在pubspec.yaml中告訴編輯器即可侧漓。只有告訴編輯器之后,我們使用import 'package:flutter/material.dart';導(dǎo)入頭文件才沒有問題监氢。
事實(shí)是這樣嗎布蔗?將pubspec.yaml第45行uses-material-design: true中的true改為false,或者將整行前面加個(gè)#注釋掉浪腐。發(fā)現(xiàn)了兩個(gè)問題:(1)導(dǎo)入頭文件并不會發(fā)生錯(cuò)誤纵揍,程序運(yùn)行一切正常(2)運(yùn)行出來的程序確實(shí)有一點(diǎn)不一樣,加號按鈕變成了一個(gè)鎖??议街。
這時(shí)候肯定會想泽谨,為什么沒發(fā)生錯(cuò)誤?按照iOS或者安卓導(dǎo)入第三方庫的經(jīng)驗(yàn)特漩,沒有加載庫吧雹,怎么可能導(dǎo)入頭文件成功。再仔細(xì)多看一眼涂身,查看material.dart的路徑雄卷,發(fā)現(xiàn)material.dart本來就是Flutter包里面的內(nèi)容。我們的AS里面本來就有Flutter包蛤售,路徑也配置好了丁鹉,pubspec.yaml第23行已經(jīng)加了Flutter庫的依賴,相當(dāng)于Flutter庫已經(jīng)導(dǎo)入到項(xiàng)目悴能,運(yùn)行當(dāng)然不會報(bào)錯(cuò)了揣钦。這個(gè)時(shí)候再看一眼Flutter包里面到底有哪些東西。
查看一下src漠酿,發(fā)現(xiàn)里面全是這些頭文件的具體實(shí)現(xiàn)拂盯。原來如此,F(xiàn)lutter就是這么個(gè)玩意记靡√父停總算懂了第一個(gè)問題团驱,那么第二個(gè)問題為啥?再看到pubspec.yaml第45行uses-material-design: true的注解部分空凸,第42行到第44行嚎花,注解如下:
# The following line ensures that the Material Icons font is
# included with your application, so that you can use the icons in
# the material Icons class.
uses-material-design: true的作用僅僅是決定Material圖標(biāo)是否應(yīng)用到項(xiàng)目中。
到這里呀洲,大概明白了material的外表是什么東西紊选。在到官網(wǎng)上和代碼中找一找,看能否發(fā)現(xiàn)更多端倪道逗。material.dart和widgets.dart是兩個(gè)頭文件兵罢,為啥我們在使用的時(shí)候沒有導(dǎo)入widgets.dart?再看一眼material.dart里面的內(nèi)容滓窍,在最下面卖词,有一個(gè)export 'widgets.dart';原來我們再導(dǎo)入material.dart之后,已經(jīng)有widgets.dart了吏夯。那么Flutter包中文件之間的關(guān)系此蜈,我們就明白了。并不是導(dǎo)入了material之后噪生,所有的類庫都會幫我們加載裆赵。在到官網(wǎng)上看看https://flutterchina.club/widgets/,發(fā)現(xiàn)Cupertino(iOS風(fēng)格的widget)是另外一個(gè)設(shè)計(jì)風(fēng)格跺嗽。同樣战授,cupertino.dart的底部也包含了widgets.dart。而animation.dart,foundation.dart等其他的文件并沒有包含widgets.dart桨嫁,那么他們之間關(guān)系陈醒,我們又清楚了更多。那開發(fā)的時(shí)候瞧甩,使用的功能屬于什么類钉跷,我們是否應(yīng)該導(dǎo)入,為什么要導(dǎo)入肚逸,就很清楚了爷辙。
兩個(gè)風(fēng)格material和cupertino,對比之下朦促,一目了然膝晾。
到目前還是沒有搞清楚return MaterialApp ,這個(gè)幫我們做了什么务冕,從哪來血当,要到哪去?command+鼠標(biāo)左鍵點(diǎn)擊進(jìn)去看看,發(fā)現(xiàn)它是位于Flutter => lib => src => material => app.dart這個(gè)路徑下面臊旭÷淠眨看一眼src =>material里面的所有文件,再隨便瀏覽一下app.dart里面的幾行代碼离熏,大概能確定佳谦,跟APP風(fēng)格,主題相關(guān)的這種全局配置定義滋戳,而且是final修飾的一大堆變量钻蔑,可能APP全局配置就在這個(gè)文件里面做了。
但是在將文件最上面的頭文件打開的時(shí)候奸鸯,發(fā)現(xiàn)app.dart里面居然有一句import 'package:flutter/cupertino.dart';app.dart居然導(dǎo)入了'package:flutter/cupertino.dart'咪笑。
所以娄涩,你別以為Material和cupertino是完全獨(dú)立窗怒,完全不同風(fēng)格的兩套組件。到cupertino的app.dart中去看钝满,并不會發(fā)現(xiàn)Material兜粘。那就有結(jié)果了申窘,Material其實(shí)是包含cupertino的弯蚜,cupertino只是對Material中某些控件的第二種封裝,部分組件提供額外一套風(fēng)格的選擇剃法。那么可以猜測一下碎捺,我們以后99%的Flutter開發(fā)項(xiàng)目都會基于Material。
繼續(xù)往下看贷洲,回到Material =》app.dart收厨,第165行const MaterialApp({,把鼠標(biāo)上下滑幾下优构,MaterialApp具體內(nèi)容暫時(shí)不管诵叁,看到this.home,this.theme猜一下钦椭,大概就是整個(gè)類里面的所有參數(shù)都可以通過MaterialApp這個(gè)方法設(shè)置拧额。再看對這個(gè)方法的注解:
/// Creates a MaterialApp.////// At least one of [home], [routes], [onGenerateRoute], or [builder] must be/// non-null. If only [routes] is given, it must include an entry for the/// [Navigator.defaultRouteName] (`/`), since that is the route used when the/// application is launched with an intent that specifies an otherwise/// unsupported route.////// This class creates an instance of [WidgetsApp].////// The boolean arguments, [routes], and [navigatorObservers], must not be null.
很明確了,這個(gè)方法是用來創(chuàng)建一個(gè)Material組件的APP彪腔,那么可以這么說侥锦,任何使用Material的APP,都會使用這個(gè)方法德挣,那么自然而然想到一個(gè)問題恭垦,每個(gè)Material組件的APP是否只會調(diào)用一次MaterialApp?如果是,那么以后根本不用管main函數(shù)在哪番挺,我們直接從MaterialApp開始不就可以了么唠帝。但會不會像iOS中scene或者根視圖那樣,可以跑多個(gè)建芙?我覺得應(yīng)該對app.dart文件搜索MaterialApp没隘,到底怎么說的?然而并沒有直接的說明這個(gè)問題禁荸,沒有任何一個(gè)地方說明可以在APP中調(diào)用兩次MaterialApp右蒲,都是用a,一個(gè)赶熟。但也只能80%肯定瑰妄,就此作罷,在往下看映砖,能否找到答案间坐。
第二句,至少[home], [routes], [onGenerateRoute], or [builder]中有一個(gè)不為空邑退。不是4個(gè)都不為空竹宋,我特意看了一下,在默認(rèn)創(chuàng)建的工程中地技,MaterialApp只有3個(gè)參數(shù):title蜈七,theme和home。我有點(diǎn)想試試莫矗,是不是真的飒硅,把title,theme注釋掉作谚,程序照常運(yùn)行三娩;但把home注釋掉,果然出錯(cuò)了
那么意思就是MaterialApp里面會包含一個(gè)根route妹懒,這個(gè)玩意就是RootViewController,整個(gè)APP不可能跳出這個(gè)根雀监。所以回頭再想,MaterialApp肯定就只會調(diào)用一次了眨唬。所以建立Material項(xiàng)目的第一步就是構(gòu)建MaterialApp会前。
再往上看看,第50行到第58行
/// An application that uses material design.////// A convenience widget that wraps a number of widgets that are commonly/// required for material design applications. It builds upon a [WidgetsApp] by/// adding material-design specific functionality, such as [AnimatedTheme] and/// [GridPaper].////// The [MaterialApp] configures the top-level [Navigator] to search for routes/// in the following order:///
可以看出還有一種構(gòu)建APP的方式WidgetsApp单绑。而MaterialApp是在WidgetsApp的基礎(chǔ)上回官,添加了material-design組件庫的功能。
在app.dart中注釋代碼中搂橙,發(fā)現(xiàn)另外一個(gè)問題歉提,每次MaterialApp都會用到Scaffold笛坦,那么Scaffold到底是什么玩意?
* [Scaffold], which provides standard app elements like an [AppBar] and a [Drawer].
我覺得應(yīng)該再研究一下Scaffold苔巨,Scaffold到底是什么版扩?做了什么,從哪來侄泽,到哪去礁芦?
初學(xué)水平有限,可能有誤悼尾,歡迎交流