日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Flutter入门篇(一)

發(fā)布時間:2024/4/14 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Flutter入门篇(一) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

距離Google發(fā)布Flutter已經(jīng)有很長一段時間了,又是一門新的技術(shù),那么我們到底是學呢還是學呢還是學呢?不要問我,我不知道,鬼特么知道我這輩子還要學習多少東西。其實新技術(shù)的出現(xiàn)也意味著,老技術(shù)會面臨淘汰危機,而你將面臨著失業(yè)危機。用一句話來說:你永遠不知道意外和驚喜哪個先來~~

環(huán)境搭建

Flutter的安裝就不在這里演示了,可以從下面幾個網(wǎng)站上學習安裝。

  • Flutter官網(wǎng)
  • Flutter中文網(wǎng)
  • Flutter社區(qū)

這些網(wǎng)站也通過豐富的Flutter學習資料

Flutter的第一個應用

在創(chuàng)建一個Flutter應用后,我們可以看到如下的demo代碼。(其中注釋是個人翻譯,如有不正確請諒解)

import 'package:flutter/material.dart';//應用啟動 void main() => runApp(MyApp());class MyApp extends StatelessWidget {// 這個App的根Widget@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo', //應用名theme: ThemeData(// 這個應用的主題//// 你用 "flutter run"運行這個應用,你將看到一個藍色的ToolBar。// 你也可以改變下面primarySwatch 的值,從Colors.blue變成 Colors.green。// 然后執(zhí)行 "hot reload" ,可以看到計數(shù)器并沒有恢復初始狀態(tài)0,這個應用也并沒有重啟。primarySwatch: Colors.blue,),home: MyHomePage(title: 'Flutter Demo Home Page'),);} }class MyHomePage extends StatefulWidget {MyHomePage({Key key, this.title}) : super(key: key);// 我們可以知道這個MyHomePage 的 widget 是這個應用的首頁,而且它是有狀態(tài)的,//這就意味著下面定義的State對象中的字段能夠影響應用的顯示。//這個類是這個狀態(tài)的配置類,它所持有的這個title值是其父類提供的,//被創(chuàng)建狀態(tài)的方法使用,在Widget的子類中總是被標記為“final”final String title;@override_MyHomePageState createState() => _MyHomePageState(); }class _MyHomePageState extends State<MyHomePage> {int _counter = 0;void _incrementCounter() {setState(() {// 回調(diào)setState去告訴Flutter framework 已經(jīng)有一些狀態(tài)發(fā)生了改變,// 讓下面這個返回Widget的build方法去展示更新的內(nèi)容。當然,如果我們沒有回調(diào)// 這個setState,那么build方法也不會被調(diào)用,也就不會有什么更新展示。_counter++;});}@overrideWidget build(BuildContext context) {// 這個方法在每次setState的時候被調(diào)用,例如上面的_incrementCounter方法。//// Flutter framework 是被優(yōu)化過的,所以它的重新運行build方法是非常快速的,只需要// 運行你需要更新的內(nèi)容,不需要去分別所有的widgets的實例。return Scaffold(appBar: AppBar(// 我們能夠使用在App.build方法中創(chuàng)建的值,并且賦值// Here we take the value from the MyHomePage object that was created by// the App.build method, and use it to set our appbar title.title: Text(widget.title),),body: Center(// Center是一個布局Widget,它提供一個child 并且規(guī)定了只能居于父類的正中心child: Column(// Column 也是一個布局Widget,它有一系列的子布局并且這些子布局都是垂直方向的。// 默認情況下,Column會調(diào)整它自己的大小去適應子級的橫向大小。//// 調(diào)用 "debug painting"可以看每一個widget的線框//// Column 有大量的屬性去控制自己的大小和它子級的位置,這里使用了mainAxisAlignment// 讓其子布局內(nèi)容是垂直方向排列。mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[Text('You have pushed the button this many times:',),Text('$_counter',style: Theme.of(context).textTheme.display1,),],),),floatingActionButton: FloatingActionButton(onPressed: _incrementCounter,tooltip: 'Increment',child: Icon(Icons.add),), // This trailing comma makes auto-formatting nicer for build methods.);} }復制代碼

運行Flutter

我使用的是Android Studio 創(chuàng)建的Flutter應用,可以看到如下所示的編譯界面

  • 點擊Run (就是那個綠色的三角)之后我們可以看到如下運行結(jié)果:

  • 點擊藍色的“+”號我們可以看到,中間的數(shù)字一直在增加,所以demo給我的是一個簡單計數(shù)器的實現(xiàn)

Demo分析

我們從官網(wǎng)知道Flutter是用Dart語言進行編碼的,我們是不是需要單獨去學習掌握這門語言呢?在我看來是不需要的,因為單獨去學習一門新的語言的過程是很枯燥的,我們可以從Demo中去學習,這樣更高效一些。所以我們來分析一下上述例子給了我們一個怎樣的知識點。

import 'package:flutter/material.dart';void main() => runApp(MyApp()); class MyApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(primarySwatch: Colors.blue,),home: MyHomePage(title: 'Flutter Demo Home Page'),);} } 復制代碼

通過上述代碼我們知道:

  • 首先導入了一個叫做material的dart文件。
  • 通過一個main()方法調(diào)用了MyApp的一個類。
  • 這個MyApp就是這個應用的入口。(根據(jù)runApp可知)

對于一個Flutter小白就會有疑問了:

  • 為什么要導入material的文件呢? 遇到這樣不明白的地方,我們就可以去官網(wǎng)查資料了,官網(wǎng)給的回答如下:

Flutter提供了許多widgets,可幫助您構(gòu)建遵循Material Design的應用程序。Material應用程序以MaterialApp widget開始, 該widget在應用程序的根部創(chuàng)建了一些有用的widget,其中包括一個Navigator, 它管理由字符串標識的Widget棧(即頁面路由棧)。Navigator可以讓您的應用程序在頁面之間的平滑的過渡。 是否使用MaterialApp完全是可選的,但是使用它是一個很好的做法。


也就是說主要是為了向開發(fā)者提供已經(jīng)實現(xiàn)好了的material設(shè)計風格,我們可以進入(Windows下Ctrl +鼠標左鍵,Mac下Command+鼠標左鍵 )material.dart源碼,可以發(fā)現(xiàn)如下:

library material;export 'src/material/about.dart'; export 'src/material/animated_icons.dart'; ... // 很多,這里就不占用大量篇幅 export 'widgets.dart'; 復制代碼

從官網(wǎng)我們知道已經(jīng)有大量的widgets供給我們使用,那么這些在哪里呢? 當然就是上面的widgets.dart文件了,我們進入這個文件中可以看到內(nèi)容大致如下:

export 'src/widgets/animated_cross_fade.dart'; ... export 'src/widgets/framework.dart'; ... export 'src/widgets/will_pop_scope.dart'; 復制代碼

也是不同的dart文件,我們進入第一個animated_cross_fade:

class AnimatedCrossFade extends StatefulWidget { /// Creates a cross-fade animation widget.... } 復制代碼

從給的注釋可以知道,這就是一個帶淡入淡出動畫的Widget,這個Widget繼承自StatefulWidget,可以看到StatefulWidget也就是繼承自Widget

abstract class StatelessWidget extends Widget {/// Initializes [key] for subclasses.const StatelessWidget({ Key key }) : super(key: key);/// Creates a [StatelessElement] to manage this widget's location in the tree.////// It is uncommon for subclasses to override this method.@overrideStatelessElement createElement() => StatelessElement(this);@protectedWidget build(BuildContext context); }abstract class StatefulWidget extends Widget {/// Initializes [key] for subclasses.const StatefulWidget({ Key key }) : super(key: key);/// Creates a [StatefulElement] to manage this widget's location in the tree.////// It is uncommon for subclasses to override this method.@overrideStatefulElement createElement() => StatefulElement(this);@protectedState createState(); } 復制代碼

到此我們驚奇的發(fā)現(xiàn),Demo代碼中的MyApp繼承的StatelessWidget原來也在這里,但是MyHomePage卻繼承自StatefulWidget,這是為什么呢?這就會引出第二個問題:

  • StatelessWidget和StatefulWidget 的區(qū)別是什么呢?

StatefulWidget可以擁有狀態(tài),這些狀態(tài)在widget生命周期中是可以變的,而StatelessWidget是不可變的。 StatefulWidget至少由兩個類組成:

  • 一個StatefulWidget類。
  • 一個 State類; StatefulWidget類本身是不變的,但是 State類中持有的狀態(tài)在widget生命周期中可能會發(fā)生變化。

StatelessWidget用于不需要維護狀態(tài)的場景,它通常在build方法中通過嵌套其它Widget來構(gòu)建UI,在構(gòu)建過程中會遞歸的構(gòu)建其嵌套的Widget


這也就是為什么MyApp是繼承自StatelessWidget 而 MyHomePage 繼承自StatefulWidget:

  • MyApp中不需要更改狀態(tài),僅僅嵌套一個MyHomePage 的Widget
  • 而MyHomePage 要繼承StatefulWidget的原因是:通過點擊+去增加數(shù)字大小,改變了顯示的狀態(tài),所以需要繼承StatefulWidget。

分析執(zhí)行方式

我們回到 MyApp這個類的build方法中,可以看到它返回了一個MaterialApp的一個Widget,在前面說過,Material Design的應用是以MaterialApp widget開始的,所以返回了一個MaterialApp

return MaterialApp(title: 'Flutter Demo', //應用名theme: ThemeData(primarySwatch: Colors.blue, // 主題色),home: MyHomePage(title: 'Flutter Demo Home Page'), // 首頁); 復制代碼

從上可以知道由于計數(shù)是一個可變的更新狀態(tài),那么就需要兩個類去實現(xiàn):

  • 一個繼承自StatefulWidget, 就是我們的MyHomePage
  • 一個繼承自State用于維護這個狀態(tài),也就是我們的_MyHomePageState
class MyHomePage extends StatefulWidget {MyHomePage({Key key, this.title}) : super(key: key);// 我們可以知道這個MyHomePage 的 widget 是這個應用的首頁,而且它是有狀態(tài)的,//這就意味著下面定義的State對象中的字段能夠影響應用的顯示。//這個類是這個狀態(tài)的配置類,它所持有的這個title值是其父類提供的,//被創(chuàng)建狀態(tài)的方法使用,在Widget的子類中總是被標記為“final”final String title;@override_MyHomePageState createState() => _MyHomePageState(); } 復制代碼

MyHomePage這個類里面沒有太多內(nèi)容:

  • 通過構(gòu)造方法將title值傳入
  • 通過createState 返回了一個_MyHomePageState的有狀態(tài)的State

到此處我們知道了實際上對數(shù)據(jù)的操作肯定就在_MyHomePageState中:

class _MyHomePageState extends State<MyHomePage> {int _counter = 0;void _incrementCounter() {setState(() {// 回調(diào)setState去告訴Flutter framework 已經(jīng)有一些狀態(tài)發(fā)生了改變,// 讓下面這個返回Widget的build方法去展示更新的內(nèi)容。當然,如果我們沒有回調(diào)// 這個setState,那么build方法也不會被調(diào)用,也就不會有什么更新展示。_counter++;});}@overrideWidget build(BuildContext context) {// 這個方法在每次setState的時候被調(diào)用,例如上面的_incrementCounter方法。//// Flutter framework 是被優(yōu)化過的,所以它的重新運行build方法是非常快速的,只需要// 運行你需要更新的內(nèi)容,不需要去分別所有的widgets的實例。return Scaffold(appBar: AppBar(// 我們能夠使用在App.build方法中創(chuàng)建的值,并且賦值title: Text(widget.title),),body: Center(// Center是一個布局Widget,它提供一個child 并且規(guī)定了只能居于父類的正中心child: Column(// Column 也是一個布局Widget,它有一系列的子布局并且這些子布局都是垂直方向的。// 默認情況下,Column會調(diào)整它自己的大小去適應子級的橫向大小。//// 調(diào)用 "debug painting"可以看每一個widget的線框//// Column 有大量的屬性去控制自己的大小和它子級的位置,這里使用了mainAxisAlignment// 讓其子布局內(nèi)容是垂直方向排列。mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[Text('You have pushed the button this many times:',),Text('$_counter',style: Theme.of(context).textTheme.display1,),],),),floatingActionButton: FloatingActionButton(onPressed: _incrementCounter,tooltip: 'Increment',child: Icon(Icons.add),), // This trailing comma makes auto-formatting nicer for build methods.);} 復制代碼

可以看出這里提供了兩個方法:build和_incrementCounter,我們已經(jīng)知道一般Widget里面的build方法返回的是一個頁面布局。

_incrementCounter的實現(xiàn)內(nèi)容很簡單: 就是使用setState方法去自增這個_counter,但此處一點要注意,更改狀態(tài)一定要使用 setState,如果不調(diào)用 setState將不會有任何的改變,即使你自增了這個_counter。(可以自己嘗試一下)

我們從注釋中可知,這個build方法在每次更新狀態(tài)(setState)的時候進行調(diào)用,我們在build的方法中增加一行打印的代碼進行驗證:

@overrideWidget build(BuildContext context) {print("build again");return Scaffold(...); 復制代碼

發(fā)現(xiàn)果然是每一次點擊+就會調(diào)用一次build方法,那這就會引出一個問題:這樣每一次都進行更新,會影響新能嗎?


Flutter framework 被優(yōu)化于快速重啟運行,只需要運行你需要更新的內(nèi)容,不需要去分別重新構(gòu)建所有的widgets的實例。


所以完全不必擔心這個每次都執(zhí)行build方法會影響性能。

從整體的布局我們知道,build返回了一個Scaffold的widget:

class Scaffold extends StatefulWidget {/// Creates a visual scaffold for material design widgets.const Scaffold({Key key,this.appBar,this.body,this.floatingActionButton,this.floatingActionButtonLocation,this.floatingActionButtonAnimator,this.persistentFooterButtons,this.drawer,this.endDrawer,this.bottomNavigationBar,this.bottomSheet,this.backgroundColor,this.resizeToAvoidBottomPadding,this.resizeToAvoidBottomInset,this.primary = true,this.extendBody = false,this.drawerDragStartBehavior = DragStartBehavior.down,}) : assert(primary != null),assert(extendBody != null),assert(drawerDragStartBehavior != null),super(key: key);復制代碼

可以知道,這個也是繼承于StatefulWidget,里面有很多可以設(shè)置的初始值,這里使用到了三個:

  • appBar-布局標題欄
  • body-內(nèi)容顯示區(qū)域
  • floatingActionButton-浮動按鈕
return Scaffold(appBar: AppBar(title: Text(widget.title),),body: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[Text('You have pushed the button this many times:',),Text('$_counter',style: Theme.of(context).textTheme.display1,),],),),floatingActionButton: FloatingActionButton(onPressed: _incrementCounter,tooltip: 'Increment',child: Icon(Icons.add),), // This trailing comma makes auto-formatting nicer for build methods.); 復制代碼

將從MyApp攜帶的title賦值給appBar的title,讓其顯示在界面頂端。內(nèi)容(body)使用了一個Center居中布局,讓其child(也是一個widget)只能顯示在當前正中位置。

class Center extends Align {/// Creates a widget that centers its child.const Center({ Key key, double widthFactor, double heightFactor, Widget child }): super(key: key, widthFactor: widthFactor, heightFactor: heightFactor, child: child); } 復制代碼

緊接著返回了一個Column的child,這個widget 是縱向排列,可有有一系列的子集,所以在Column 布了兩個Text,一個顯示固定文本,一個顯示可變的文本:

class Column extends Flex {Column({Key key,MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,MainAxisSize mainAxisSize = MainAxisSize.max,CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,TextDirection textDirection,VerticalDirection verticalDirection = VerticalDirection.down,TextBaseline textBaseline,List<Widget> children = const <Widget>[],}) : super(children: children,key: key,direction: Axis.vertical,mainAxisAlignment: mainAxisAlignment,mainAxisSize: mainAxisSize,crossAxisAlignment: crossAxisAlignment,textDirection: textDirection,verticalDirection: verticalDirection,textBaseline: textBaseline,); } 復制代碼

需要注意的是,對變量的占位符使用的$符號,就跟java中使用%是一樣的。 最后一個就是我們點擊事件的按鈕floatingActionButton,通過onPressed去調(diào)用_incrementCounter方法實現(xiàn)自增計數(shù)。 整個運行的流程就到這里算是講完了。

Hot Reload(熱加載)

在文章開始的時候我們知道,我們有一個一道雷一樣的圖標,那就是Hot Reload,這個怎么個意思呢?就是說你如果更新了你的代碼,不用重新運行整個都重新運行,直接使用這個就可以了,可以很迅速的將你更新的內(nèi)容重新顯示。 在這里有一個很有意思的事情: 我們點擊+讓計數(shù)器顯示到1,然后將主題的顏色改成綠色:primarySwatch: Colors.green,

class MyApp extends StatelessWidget {// This widget is the root of your application.@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',theme: ThemeData(// 主題從藍色更改為綠色primarySwatch: Colors.green,),home: MyHomePage(title: 'Flutter Demo Home Page'),);} } 復制代碼

然后點擊hot reload 會發(fā)現(xiàn),我們的主題更改為綠色了,但是我的計數(shù)器顯示的數(shù)字仍然是1,并沒有變成0。這也印證了上面的那句話,hot reload只會更改所需要更改的內(nèi)容,不會影響全部。

總結(jié)

這里在做一個總結(jié),希望對才你有所幫助

  • 在flutter中,絕大部分可使用的內(nèi)容都是widget
  • 如果只是顯示內(nèi)容,不涉及更改狀態(tài),就是用StatelessWidget;如果涉及狀態(tài)的變更就是用StatefulWidget
  • StatefulWidget的實現(xiàn)需要兩步:一個是需要創(chuàng)建繼承StatefulWidget的類;另一個就是創(chuàng)建繼承State的類,一般在State中控制整個狀態(tài)。
  • 更新狀態(tài)一定要調(diào)用setState方法,不然不會起作用
  • hot reload只會影響更改的內(nèi)容

總結(jié)

以上是生活随笔為你收集整理的Flutter入门篇(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。