Flutter 帶你快速入門

帶你高效入門 Flutter

本文面向 Flutter 初學(xué)者诉儒,旨在用易懂的方式帶大家入門。除了 Flutter 代碼淆衷,還會(huì)介紹到語法缸榄、原理、特性等基礎(chǔ)知識(shí)祝拯。相信本文能幫助你學(xué)習(xí)和理解 Flutter甚带。

跨平臺(tái)技術(shù)簡介

我們先看一下目前的一些跨平臺(tái)方案,從前端渲染的角度來分類的話鹿驼,大致可以分為以下幾種方案欲低。

WebView 渲染

這種方案就很好理解,現(xiàn)在很多項(xiàng)目都會(huì)嵌入 H5 的頁面畜晰。就是用 JavaScript 等前端技術(shù)進(jìn)行開發(fā),在客戶端上用 WebView 來進(jìn)行渲染凄鼻。微信小程序目前使用的就是這種方案。

微信小程序

它的優(yōu)點(diǎn)很明顯闰非,使用成熟的前端技術(shù)進(jìn)行開發(fā)峭范,學(xué)習(xí)成本低财松,開發(fā)效率高,并且支持動(dòng)態(tài)發(fā)布代碼。

但缺點(diǎn)也很明顯辆毡,在性能體驗(yàn)上菜秦,和原生還是存在較大差距的。

原生控件渲染

既然 WebView 的性能不夠好舶掖,于是就有了使用原生控件進(jìn)行渲染的方案球昨。這種方案,同樣也是使用 JavaScript 開發(fā)眨攘,區(qū)別是它最終是調(diào)用原生控件進(jìn)行渲染的主慰。這種方案的代表是 Facebook 的 React Native。

React Native

由于使用原生控件進(jìn)行渲染鲫售,性能體驗(yàn)也會(huì)更接近原生共螺。但也只是更接近,和原生還是有差距的龟虎,因?yàn)樗枰l繁的進(jìn)行 JavaScript 和原生之間的通信璃谨,這個(gè)通信效率是比較低的。

另外鲤妥,由于需要適配各個(gè)平臺(tái)的控件佳吞,那就有可能出現(xiàn),系統(tǒng)控件更新了棉安,而框架本身還沒有更新底扳,由此產(chǎn)生了一些問題。換句話說贡耽,這種方案是受到原生控件限制的衷模。

繪圖引擎渲染

接下來就是主角了。

在前端蒲赂,如果完全不使用原生控件木蹬,我們可以通過系統(tǒng)的繪圖 API 繪制出一個(gè)用戶界面镊叁。從這個(gè)角度出發(fā)晦譬,可以在各個(gè)平臺(tái)使用一個(gè)統(tǒng)一接口的繪圖引擎來進(jìn)行界面繪制敛腌,這個(gè)引擎最終調(diào)用的是系統(tǒng)的 API 繪制的夸溶。這樣的話,它的性能可以做到接近原生足绅,并且又不受原生控件的限制氢妈,在不同平臺(tái)上能夠做到 UI 統(tǒng)一首量。

Flutter 就是這樣的一個(gè)開發(fā)框架加缘。

Flutter

Flutter 簡介

一個(gè)跨平臺(tái) UI 解決方案

Flutter 是由 Google 開發(fā)的,一個(gè)跨平臺(tái) UI 解決方案勋乾。換句話說辑莫,它原則上只管 UI 的問題,如果涉及到平臺(tái)本身的一些功能绅你,比如調(diào)用藍(lán)牙忌锯、攝像頭偶垮,一般還是需要原生代碼去操作脚猾。但現(xiàn)在也會(huì)有一些第三方庫幫我們解決這些問題龙助。

繪圖引擎 Skia

Skia

Flutter 使用 Skia 作為它的繪圖引擎。Skia 已經(jīng)被 Google 收購仅淑,目前很多 Google 旗下的產(chǎn)品都是用 Skia 繪制的赡鲜,包括 Android庐船。

Android 內(nèi)置了 Skia捡硅,但 iOS 沒有壮韭,所以在打 iOS 安裝包的時(shí)候喷屋,會(huì)把 Skia 一起打進(jìn)去。這就導(dǎo)致了恶耽,用同一份 Flutter 代碼打包之后偷俭,iOS 的包要比 Android 的包大一些涌萤。

開發(fā)語言 Dart

Dart

Flutter 使用的開發(fā)語言透揣,叫 Dart辐真。Dart 也是 Google 自家的拆祈,它是一門面向?qū)ο蟮恼Z言咙咽,從它身上會(huì)看到一些其他開發(fā)語言的影子蜡豹。學(xué)習(xí)起來難度不大的镜廉。

前面講跨平臺(tái)方案的時(shí)候娇唯,可以發(fā)現(xiàn)別的方案基本都是用 JavaScript 作為開發(fā)語言的,但為什么 Flutter 不用想许?就因?yàn)?Dart 是谷歌自家的嗎流纹?這個(gè)問題先留著漱凝,我們后面會(huì)提到碉哑。

搭建開發(fā)環(huán)境

這里部分就簡單點(diǎn)帶過了妆毕,具體的搭建流程可以在官網(wǎng)查看:

flutter-io.cn/docs/get-st…

主要的搭建步驟如下:

下載 Flutter SDK

官網(wǎng)下載地址:

flutter.dev/docs/develo…

由于在國內(nèi)訪問可能受限笛粘,官方為中國開發(fā)者搭建了鏡像:

flutter.dev/community/c…

更新環(huán)境變量

解壓后,將 flutter\bin 的全路徑添加到環(huán)境變量 PATH 中示括。

安裝開發(fā)工具

理論上垛膝,任何文本編輯器都可以用來開發(fā) Flutter 應(yīng)用,但推薦的開發(fā)工具是 Android Studio凿可、IntelliJ 以及 VS Code枯跑。因?yàn)樵谶@些開發(fā)工具上,可以安裝官方的 Flutter 和 Dart 插件辜腺,得到更好的開發(fā)體驗(yàn)。文章里使用 Android Studio 來演示茵烈。

如果你打算開發(fā) iOS 應(yīng)用加匈,則還需要安裝 Xcode雕拼。

安裝插件

在開發(fā)工具的插件設(shè)置中偎球,安裝上面說到的 Flutter 和 Dart 插件。Flutter 插件用于支持 Flutter 的運(yùn)行磷醋、調(diào)試镊掖、熱重載等功能,而 Dart 插件則提供了代碼的輸入校驗(yàn)症虑、代碼補(bǔ)全等功能缩歪。

Hello World!

萬物始于 Hello World,我們先來創(chuàng)建一個(gè)顯示 Hello World 的 Flutter 項(xiàng)目谍憔。

在 Android Studio 的歡迎頁面選擇 Start a new Flutter project匪蝙,或者通過菜單欄的 File > New > New Flutter Project,創(chuàng)建一個(gè)新的 Flutter 項(xiàng)目习贫。

創(chuàng)建好的項(xiàng)目里面包含了 android 和 ios 兩個(gè)文件夾逛球,它們是標(biāo)準(zhǔn)的 Android 和 iOS 項(xiàng)目。我們的 Flutter 代碼颤绕,存放在 lib 文件夾里。項(xiàng)目創(chuàng)建好后官研,會(huì)默認(rèn)帶一個(gè)計(jì)數(shù)器的示例,我們不管它,把 main.dart 的代碼改成 Hello World:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
            appBar: AppBar(title: Text("Hello")),
            body: Center(child: Text("Hello World!", style: TextStyle(fontSize: 32)))));
  }
}
復(fù)制代碼

啟動(dòng)一個(gè)模擬器溜族,或者連上真機(jī),點(diǎn)擊 Run 運(yùn)行一下组民,就能看這樣一個(gè)界面了:

Hello World

具體代碼先混個(gè)眼熟就好,具體的后面會(huì)再講到。

Dart 語法

在寫 Flutter 之前膜廊,還要先跟大家簡單介紹一下 Dart 的語法。如果你有 Java 或 JavaScript 的開發(fā)經(jīng)驗(yàn),以及面向?qū)ο蟮木幊趟枷胨澳龋瑢W(xué)起來是很快的。

我們可以在 test 文件夾下新建一個(gè) dart 文件,用來寫測(cè)試代碼。

變量聲明

指定類型

和 java 一樣巫俺,我們可以這樣來聲明一個(gè)整形變量:

int num = 666;
復(fù)制代碼

var

同時(shí),我們也可以像 JavaScript 一樣骤竹,用 var 來聲明:

var num = 666;
復(fù)制代碼

但和 JavaScript 不同的是,以下代碼在 JavaScript 是不會(huì)報(bào)錯(cuò)的锨匆,但在 Dart 里會(huì)報(bào)錯(cuò):

var num = 666;

void main() {
  num = "666"; // 報(bào)錯(cuò)
}
復(fù)制代碼

在 Dart 里用 var 聲明一個(gè)變量之后诀姚,它會(huì)根據(jù)第一次賦值,來推斷變量的類型,之后就不能再改變類型了。也就是說,JavaScript 是一種弱類型的語言桦锄,而 Dart 是一種強(qiáng)類型的語言。

Object

如果非要上面這樣寫黑毅,那也可以。把 var 換成 Object 就不報(bào)錯(cuò)了:

Object num = 666;

void main() {
  num = "666";
}
復(fù)制代碼

和 Java 類似,Object 是所有對(duì)象的根基類。但是這樣的話碾篡,如果想打印一下 num 的字符串長度,是會(huì)報(bào)錯(cuò)的:

Object num = 666;

void main() {
  num = "666";
  print(num.length); // 報(bào)錯(cuò)
}
復(fù)制代碼

因?yàn)?length 是屬于 String 的技即,但系統(tǒng)只知道 num 是一個(gè)對(duì)象,并不知道它是一個(gè) String樟遣。

dynamic

如果還是非要這樣寫而叼,那也可以。Dart 有一個(gè)特有的關(guān)鍵字 dynamic豹悬,把 Object 改成 dynamic 就不報(bào)錯(cuò)了:

dynamic num = 666;

void main() {
  num = "666";
  print(num.length);
}
復(fù)制代碼

我們運(yùn)行一下這個(gè)文件葵陵,可以在控制臺(tái)看到正確打印出了字符串長度。

dynamic 是動(dòng)態(tài)的意思瞻佛,使用它聲明的話脱篙,系統(tǒng)會(huì)去找到可用的屬性和函數(shù)來調(diào)用。但這種寫法其實(shí)是不太安全的,因?yàn)榧词鼓惆褜傩悦村e(cuò)了绊困,編譯器也是不會(huì)報(bào)錯(cuò)的文搂,要到運(yùn)行時(shí)才會(huì)報(bào)錯(cuò)。

函數(shù)

dynamic

在 Dart 里秤朗,函數(shù)也是可以不寫返回類型的煤蹭,不寫的話會(huì)被當(dāng)做 dynamic 來處理。這樣的話川梅,函數(shù)的類型就是 return 的類型疯兼,如果沒有 return 則是 void 類型。比如可以這樣:

main() {
  print(getNum().length);
}

getNum(){
  return "666";
}
復(fù)制代碼

運(yùn)行之后是能正確打印出字符串長度的贫途。

用于傳參

Dart 里的函數(shù)也是一個(gè)對(duì)象吧彪,所以可以把函數(shù)作為參數(shù)來傳遞,比如:

main() {
  execute(print666);
}

print666() {
  print("666");
}

execute(Function fun){
  fun();
}
復(fù)制代碼

可選參數(shù)

在 Dart 的函數(shù)傳參里丢早,有一個(gè)叫可選參數(shù)的概念姨裸,我們以文字控件 Text 為例,在源碼里可以看到 Text 的構(gòu)造函數(shù)是這樣的:

const Text(
    this.data, {
    Key key,
    this.style,
    this.strutStyle,
    this.textAlign,
    this.textDirection,
    this.locale,
    this.softWrap,
    this.overflow,
    this.textScaleFactor,
    this.maxLines,
    this.semanticsLabel,
})
復(fù)制代碼

首先怨酝,在參數(shù)里有一個(gè) data傀缩,它是要顯示的文字內(nèi)容,是一個(gè)必填項(xiàng)农猬。而 data 后面的一堆參數(shù)赡艰,是用一個(gè)大括號(hào)括起來的,這些參數(shù)就叫做可選參數(shù)斤葱,意思是這些參數(shù)可傳可不傳慷垮。

假如我們要顯示一個(gè)比較長的文字,又想限制它最多顯示兩行揍堕,就可以這樣來創(chuàng)建一個(gè) Text:

new Text("666666666666", maxLines: 2); 
復(fù)制代碼

可選參數(shù)料身,在 Flutter 里面用的非常多。

異步

Future

在 Dart 里使用 Future 來處理異步任務(wù)衩茸,比如我們現(xiàn)在延時(shí)一秒打印 666芹血,代碼如下:

void main() {
  Future.delayed(new Duration(seconds: 1), () {
    return "666";
  }).then((data) {
    // 成功后執(zhí)行
    print(data);
  }).catchError((e) {
    // 失敗后執(zhí)行
    print("error");
  }).whenComplete(() {
    // 無論成功失敗都會(huì)執(zhí)行
    print("complete");
  });
}
復(fù)制代碼

Future 的語法和 Promise 非常像。任務(wù)執(zhí)行成功會(huì)調(diào)用 then楞慈,執(zhí)行失敗會(huì)調(diào)用 catchError幔烛,而無論成功還是失敗,都會(huì)調(diào)用 whenComplete囊蓝。

async/await

如果你不喜歡上面那種寫法说贝,或者是想把異步轉(zhuǎn)成同步,就可以用 async 和 await 這兩個(gè)關(guān)鍵字來轉(zhuǎn)換慎颗。

我們把上面的代碼轉(zhuǎn)換一下,寫一個(gè) getString 方法,返回的類型是 Future俯萎,它會(huì)延時(shí)返回一個(gè)字符串傲宜。在 main 函數(shù)后面加上 async 關(guān)鍵字,在 getString() 前面加上 await夫啊,代碼如下:

void main() async{
  print(await getString());
}

getString() {
  return Future.delayed(new Duration(seconds: 1), () {
    return "666";
  });
}
復(fù)制代碼

運(yùn)行之后可以看到函卒,能正常延時(shí)一秒后,把字符串打印出來撇眯。這里 getString() 返回的類型是 Future报嵌,而 await getString() 則是返回了延時(shí)之后返回的字符串。await 要在 async 的函數(shù)里面才能使用熊榛。

async 和 await 其實(shí)是一個(gè)語法糖锚国,它最終也是轉(zhuǎn)換成 Future 調(diào)用鏈的形式執(zhí)行的。

萬物皆控件

接下來回到 Flutter玄坦,F(xiàn)lutter 里最重要的一個(gè)概念是 Widget(下面翻譯作控件)血筑。

在原生開發(fā)里面,我們可能會(huì)在界面上區(qū)分煎楣,這是一個(gè) View豺总,這是一個(gè) Layout,這是一個(gè) View Controller择懂。但在 Flutter 里面喻喳,它們?nèi)紝儆谝粋€(gè)統(tǒng)一的模型 Widget±铮可以說表伦,在 Flutter 界面里,所有東西都是 Widget赂弓。

以前學(xué)面向?qū)ο蟮臅r(shí)候绑榴,我們都聽過一句話,叫萬物皆對(duì)象盈魁。我這里套用一下翔怎,在 Flutter 里,萬物皆控件杨耙。

具體有哪些控件赤套,我做了一下簡單的分類。

根控件

class MyPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MyWidget();
  }
}
復(fù)制代碼

所有的控件都屬于 StatefulWidgetStatelessWidget珊膜。它們的區(qū)別是容握,StatefulWidget 擁有狀態(tài) State,而 StatelessWidget 沒有车柠。

StatefulWidget

當(dāng)一個(gè)控件是可變的時(shí)候剔氏,就要使用 StatefulWidget 來構(gòu)建塑猖。StatefulWidget 本身不可變,但它持有的狀態(tài) State 是可變的谈跛。

StatelessWidget

當(dāng)一個(gè)控件狀態(tài)是固定不可變的時(shí)候羊苟,就可以使用 StatelessWidget。前面我們寫的 Hello World 就是使用 StatelessWidget感憾。

容器控件

Center(
    child: MyWidget()
)
復(fù)制代碼

容器類控件一般是將某些屬性或配置蜡励,作用在它的子控件上,比如控件所在的寬高阻桅、背景凉倚、位置等。

常用的容器控件有 Container嫂沉、Center稽寒、Padding 等。

布局控件

Column(children: <Widget>[
    MyWidget1(),
    MyWidget2()
])
復(fù)制代碼

布局控件可以類比作原生開發(fā)中的 Layout输瓜,通常它會(huì)擁有一個(gè) children 的屬性瓦胎,用于接收一個(gè)控件數(shù)組,對(duì)這些控件進(jìn)行特定的排版尤揣。

常用的布局控件有 Row搔啊、Column、Stack北戏、Flex 等负芋。

基礎(chǔ)控件

Text("666")
復(fù)制代碼

基礎(chǔ)控件就是常用的文字、按鈕嗜愈、圖片等控件旧蛾。

常用的基礎(chǔ)控件有 Text、TextField蠕嫁、Button锨天、Image 等。

功能控件

Navigator.of(context).push(MaterialPageRoute(builder: (context) {
    return NewPage();
}));
復(fù)制代碼

在 Flutter 里還有一類控件剃毒,它們不影響 UI 布局病袄,但帶有一些特定的功能,比如頁面跳轉(zhuǎn)赘阀、事件監(jiān)聽益缠、定義主題等。我們把這一類控件稱作功能控件基公。

常用的功能控件有 Navigator幅慌、NotificationListener、Theme 等轰豆。

計(jì)數(shù)器

開始寫 Flutter 代碼了胰伍。還記不記得齿诞,在 Flutter 項(xiàng)目創(chuàng)建之后,是自帶一個(gè)計(jì)數(shù)器 demo 的骂租,現(xiàn)在我們用自己的代碼實(shí)現(xiàn)一遍掌挚。代碼修改成如下:

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: MyPage());
  }
}

class MyPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return MyPageState();
  }
}

class MyPageState extends State<MyPage> {
  int num = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("計(jì)數(shù)器"),
        ),
        body: Center(
            child: Text(
                num.toString(), 
                style: TextStyle(fontSize: 36)
            )
        ),
        floatingActionButton: FloatingActionButton(
            child: Icon(Icons.add),
            onPressed: () {
              setState(() {
                num++;
              });
            }));
  }
}
復(fù)制代碼

運(yùn)行之后嫌术,就可以看到這樣的界面了:

計(jì)數(shù)器

按鈕每點(diǎn)擊一次格嘁,數(shù)字就會(huì)加一俱箱。下面我們來分析一下這段代碼,看下里面用到的一些 Widget抽米。

StatefulWidget

由于頁面中的數(shù)字是跟隨狀態(tài)變化的,所以該頁面改用 StatefulWidget糙置。StatefulWidget 并不會(huì)直接返回一個(gè) Widget云茸,而是返回狀態(tài) State,在 State 里再返回 Widget谤饭。

Scaffold

Scaffold 是一個(gè)標(biāo)準(zhǔn)的 Material Design 頁面标捺,它包含了標(biāo)題欄、浮動(dòng)按鈕揉抵、側(cè)滑菜單亡容、底部導(dǎo)航欄等配置。我們這里用到了標(biāo)題欄 appBar冤今、頁面內(nèi)容 body闺兢、浮動(dòng)按鈕 floatingActionButton。

AppBar

AppBar 就是標(biāo)題欄戏罢,通過查看控件的構(gòu)造方法屋谭,我們可以知道它可配置的屬性。

AppBar 的可選參數(shù)除了標(biāo)題 title龟糕,還可以配置標(biāo)題前的內(nèi)容 leading桐磁,右側(cè)的操作按鈕 anctions,控件垂直高度 elevation 等讲岁。我們只傳了 title我擂,其他屬性都用默認(rèn)值。

Center

Center 是一個(gè)容器類控件催首,它的作用就是讓它的子控件居中顯示扶踊。

FloatingActionButton

熟悉安卓開發(fā)的應(yīng)該對(duì)這個(gè)控件比較熟悉,它就是頁面右下角一個(gè)特定樣式的 Button郎任,參數(shù)里面的 onPressed 是一個(gè)必填項(xiàng)秧耗,要傳一個(gè)點(diǎn)擊之后的回調(diào)函數(shù)。

根據(jù)這個(gè)例子舶治,下面給大家介紹一下 Flutter 兩個(gè)比較重要的特性分井。

響應(yīng)式 UI

點(diǎn)擊 Button 之后车猬,我們把 num 變量加一,并使用 setState 通知狀態(tài)發(fā)生了改變尺锚,F(xiàn)lutter 會(huì)根據(jù)新的狀態(tài)更新 UI珠闰。如果有接觸過小程序開發(fā),setState 就和小程序的 setData 類似瘫辩。

在 Flutter 里面我們不需要用 set 方法來更新 UI伏嗜,可變控件是和狀態(tài)綁定的,這就是 Flutter 的響應(yīng)式 UI 編程伐厌。

熱重載

在 Android Q 和 iOS 13 里都加入了暗黑模式承绸,我們也換一個(gè)暗黑主題來玩一下。MaterialApp 里有一個(gè) theme 的屬性挣轨,我們把它配置一下:

return MaterialApp(
    theme: ThemeData.dark(), 
    home: MyPage()
);
復(fù)制代碼

這次改完之后不點(diǎn) Run 了军熏,我們點(diǎn)一下閃電圖標(biāo) Flutter Hot Reload,就能看到界面發(fā)生了變化:

image

這就是 Flutter 的熱重載卷扮,在修改完代碼之后荡澎,通過熱重載就能馬上在設(shè)備上看到修改結(jié)果,可以很大程度上增加開發(fā)效率晤锹。

下面再給大家介紹幾個(gè) Flutter 里的常見操作摩幔。

頁面跳轉(zhuǎn)

在 Flutter 里,使用 Navigator 來管理頁面跳轉(zhuǎn)抖甘,比如要跳轉(zhuǎn)到一個(gè) NewPage 可以這樣寫:

Navigator.of(context).push(MaterialPageRoute(builder: (context) {
    return NewPage();
}));
復(fù)制代碼

進(jìn)棧使用 push热鞍,出棧則是 pop。

使用 MaterialPageRoute 會(huì)模擬出 Android 上頁面跳轉(zhuǎn)的過場(chǎng)效果衔彻。

本地圖片

我們來看看怎么顯示一張本地圖片薇宠。

先在根目錄新建一個(gè)存放圖片的文件夾,比如叫 images艰额,把圖片 picture.png 放進(jìn)去澄港。

找到根目錄下的 pubspec.yaml 文件,這個(gè)便是 Flutter 依賴配置文件柄沮,我們需要在這里配置一下剛才的圖片:

  assets:
    - images/picture.png
復(fù)制代碼

這樣回梧,我們就能使用 Image 控件把這張圖片顯示出來了:

Image.asset("images/picture.png"))
復(fù)制代碼

引入第三方庫

和 node 的 npm 以及 Android 的 jcenter 類似,F(xiàn)lutter 也擁有一個(gè)公共倉庫 pub.dev祖搓。pub.dev 是 Google 官方的 Dart 倉庫狱意,在上面可以找到我們需要的包和插件。

Flutter 本身沒有 Toast拯欧,我們來接入一個(gè)详囤。在 pub.dev 上搜索后,我決定使用 fluttertoast

image

按照說明,在 pubspec.yaml 文件里的 dependencies 下配置:

  fluttertoast: ^3.1.0
復(fù)制代碼

點(diǎn)一下 Android Studio 右上角的 Packages get 同步之后就可以使用了:

Fluttertoast.showToast(msg: "666666");
復(fù)制代碼

iOS 樣式

我們上面使用的都是 Material Design 的控件藏姐,它們都是在 flutter/material.dart 包里面的隆箩。如果要使用 iOS 風(fēng)格的控件,則要用到 flutter/cupertino.dart 包:

import 'package:flutter/cupertino.dart';
復(fù)制代碼

iOS 風(fēng)格的控件羔杨,基本都以 Cupertino 開頭捌臊。我們把計(jì)時(shí)器頁面里的控件替換一下:

import 'package:flutter/cupertino.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CupertinoApp(home: MyPage());
  }
}

class MyPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return MyPageState();
  }
}

class MyPageState extends State<MyPage> {
  int num = 0;

  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
        navigationBar: CupertinoNavigationBar(
          middle: Text("計(jì)數(shù)器"),
        ),
        child: Container(
            width: double.infinity,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: <Widget>[
                Text(num.toString(), style: TextStyle(fontSize: 36)),
                CupertinoButton(
                    color: CupertinoColors.activeBlue,
                    child: Icon(CupertinoIcons.add),
                    onPressed: () {
                      setState(() {
                        num++;
                      });
                    })
              ],
            )));
  }
}
復(fù)制代碼

效果如下:

image

編譯方式

代碼的部分就到這里了,接下來跟大家聊一下編譯方式兜材,編程語言的編譯方式有兩種理澎。

  • JIT (Just in time) - 邊運(yùn)行、邊編譯

  • AOT (Ahead of time) - 先編譯曙寡,再運(yùn)行

關(guān)于它們孰優(yōu)孰劣矾端,就要看從哪個(gè)角度去對(duì)比了。JIT 的話卵皂,它的一大特點(diǎn)就是支持動(dòng)態(tài)發(fā)布代碼,也就是支持熱更新砚亭。但要是從性能的角度考慮灯变,AOT 會(huì)更好,因?yàn)樵谶\(yùn)行的時(shí)候不用再進(jìn)行編譯的操作的捅膘,運(yùn)行的效率會(huì)更高一些添祸。

回到我們一開始的時(shí)候留下的問題,為什么別的跨平臺(tái)方案都是用 JavaScript寻仗,而 Flutter 要用 Dart 來開發(fā)刃泌。JavaScript 的編譯方式是 JIT 的,它不支持 AOT署尤。而 Dart 同時(shí)支持 JIT 和 AOT耙替。

Flutter 在開發(fā)階段使用 JIT,讓我們用上了熱重載曹体,增加了開發(fā)效率俗扇。在打包時(shí)改用 AOT,保證了正式版應(yīng)用的性能箕别。

熱更新铜幽?

最后講一下大家比較關(guān)心的一個(gè)東西,F(xiàn)lutter 是否支持熱更新串稀?前面說到 Dart 支持 JIT除抛,所以從技術(shù)層面它是支持的。但是目前是不支持的母截,在官方的計(jì)劃文檔中到忽,可以看到:

image

至于原因,官方在這里進(jìn)行了說明微酬』媲鳎總的來說颤陶,是由于政策的限制,以及出于對(duì)性能和安全性的考慮陷遮,暫時(shí)不支持了滓走。

結(jié)束

到這就結(jié)束啦。由于想把 Flutter 基礎(chǔ)在一篇內(nèi)講完帽馋,沒有涉及太多細(xì)節(jié)搅方,如果要寫 Flutter 代碼還需要深入學(xué)習(xí)。但相信理解之后再學(xué)绽族,會(huì)輕松很多姨涡。

妥妥的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末吧慢,一起剝皮案震驚了整個(gè)濱河市涛漂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌检诗,老刑警劉巖匈仗,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異逢慌,居然都是意外死亡悠轩,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門攻泼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來火架,“玉大人,你說我怎么就攤上這事忙菠『渭Γ” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵牛欢,是天一觀的道長音比。 經(jīng)常有香客問我,道長氢惋,這世上最難降的妖魔是什么洞翩? 我笑而不...
    開封第一講書人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮焰望,結(jié)果婚禮上骚亿,老公的妹妹穿的比我還像新娘。我一直安慰自己熊赖,他們只是感情好来屠,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般俱笛。 火紅的嫁衣襯著肌膚如雪捆姜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評(píng)論 1 285
  • 那天迎膜,我揣著相機(jī)與錄音泥技,去河邊找鬼。 笑死磕仅,一個(gè)胖子當(dāng)著我的面吹牛珊豹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播榕订,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼店茶,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了劫恒?” 一聲冷哼從身側(cè)響起贩幻,我...
    開封第一講書人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎两嘴,沒想到半個(gè)月后段直,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡溶诞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了决侈。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片螺垢。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖赖歌,靈堂內(nèi)的尸體忽然破棺而出枉圃,到底是詐尸還是另有隱情,我是刑警寧澤庐冯,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布孽亲,位于F島的核電站,受9級(jí)特大地震影響展父,放射性物質(zhì)發(fā)生泄漏返劲。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一栖茉、第九天 我趴在偏房一處隱蔽的房頂上張望篮绿。 院中可真熱鬧,春花似錦吕漂、人聲如沸亲配。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽吼虎。三九已至犬钢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間思灰,已是汗流浹背玷犹。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留官辈,地道東北人箱舞。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像拳亿,于是被迫代替她去往敵國和親晴股。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 本文面向 Flutter 初學(xué)者肺魁,旨在用易懂的方式帶大家入門电湘。除了 Flutter 代碼,還會(huì)介紹到語法鹅经、原理寂呛、特...
    NanBox閱讀 2,839評(píng)論 0 6
  • 特別說明 當(dāng)前博客平臺(tái)賬號(hào)已廢棄,如果有使用細(xì)節(jié)問題請(qǐng)前往我新博客平臺(tái)進(jìn)行討論交流瘾晃。 個(gè)人博客平臺(tái) HuRuWo的...
    善篤有余劫閱讀 4,940評(píng)論 0 30
  • 目錄 一贷痪、Flutter 為何使用Dart開發(fā)語言二、Flutter的UI系統(tǒng)1.特點(diǎn)2.架構(gòu)簡介2.1 Flut...
    十拿九穩(wěn)啦閱讀 3,632評(píng)論 3 28
  • 一. 《教父》中有句臺(tái)詞:“花半秒鐘就看透事物本質(zhì)的人蹦误,和花一輩子都看不清事物本質(zhì)的人劫拢,注定是截然不同的命運(yùn)∏恳龋” ...
    HF的平方閱讀 2,307評(píng)論 4 15
  • 去天津說來也幾年了偶洋,一個(gè)城市的繁華與冷清熟吏,現(xiàn)代與古樸,忙碌與空虛玄窝,都漸漸的融入了我的生活牵寺。從最初的本能排斥,到現(xiàn)在...
    遇見丹噶爾的Tomorrow閱讀 364評(píng)論 0 0