一. Flutter官網(wǎng)
英文: https://flutter.io/
中文: https://flutterchina.club/
二. Flutter簡介
Flutter是谷歌的移動(dòng)UI框架,可以快速在iOS和Android上構(gòu)建高質(zhì)量的原生用戶界面。 Flutter可以與現(xiàn)有的代碼一起工作。在全世界,F(xiàn)lutter正在被越來越多的開發(fā)者和組織使用,并且Flutter是完全免費(fèi)、開源的。并且Flutter是一款移動(dòng)應(yīng)用程序SDK,一份代碼可以同時(shí)生成iOS和Android兩個(gè)高性能、高保真的應(yīng)用程序。
Flutter目標(biāo)是使開發(fā)人員能夠交付在不同平臺(tái)上都感覺自然流暢的高性能應(yīng)用程序。我們兼容滾動(dòng)行為、排版、圖標(biāo)等方面的差異。以及Flutter可以對項(xiàng)目進(jìn)行熱更新修復(fù),以最快的速度進(jìn)行線上項(xiàng)目Bug的修復(fù).
Flutter目前可以跨平臺(tái)能力目前可以支持, Linux , Android, iOS, Fuchsia.
對比Cordova框架,Flutter框架不是基于Web技術(shù)的框架.
Flutter能達(dá)到120 FPS超高性能.
使用Flutter搭建的官方App
gitme下載地址如下:

Flutter開發(fā), 為四端不同平臺(tái)的開發(fā)者單獨(dú)列舉了相應(yīng)的文檔信息.
iOS, Android, Web, React Native, 針對移動(dòng)端開發(fā)工程師熟悉程度,列舉不同的文檔, 進(jìn)行對比式, 進(jìn)行講解, 易于開發(fā)人員進(jìn)行理解.
由于樓主是做iOS開發(fā)出身的,所以此處著重針對iOS開發(fā)進(jìn)行對比. Flutter框架的主要編程語言為Dart, 此語言類似JS, 所以有JS基礎(chǔ)的童鞋上手會(huì)很快.
三. 針對iOS開發(fā)者接觸Flutter
UIView相當(dāng)于Flutter中的什么?
在iOS中, 構(gòu)建UI的過程中將使用大量的view對象,或者是以UIView為容器,承載其他的UI控件,最終渲染整個(gè)頁面繪制UI.
然而在Flutter中, 對比的認(rèn)為Widget相當(dāng)于UIView, 但是Widget和iOS中的控件并不完全等價(jià).Widget 和 UIView 還是有些區(qū)別的。首先,widgets 擁有不同的生存時(shí)間:它們一直存在且保持不變,直到當(dāng)它們需要被改變。當(dāng) widgets 和它們的狀態(tài)被改變時(shí),F(xiàn)lutter 會(huì)構(gòu)建一顆新的 widgets 樹。作為對比,iOS 中的 views 在改變時(shí)并不會(huì)被重新創(chuàng)建。但是與其說 views 是可變的實(shí)例,不如說它們被繪制了一次,并且直到使用 setNeedsDisplay() 之后才會(huì)被重新繪制。此外,不像 UIView,由于不可變性,F(xiàn)lutter 的 widgets 非常輕量。這是因?yàn)樗鼈儽旧聿⒉皇鞘裁纯丶?,也不?huì)被直接繪制出什么,而只是 UI 的描述。
Flutter 包含了 Material 組件庫。這些 widgets 遵循了 Material 設(shè)計(jì)規(guī)范。MD 是一個(gè)靈活的設(shè)計(jì)系統(tǒng),并且為包括 iOS 在內(nèi)的所有系統(tǒng)進(jìn)行了優(yōu)化。
但是用 Flutter 實(shí)現(xiàn)任何的設(shè)計(jì)語言都非常的靈活和富有表現(xiàn)力。在 iOS 平臺(tái),你可以使用 Cupertino widgets 來構(gòu)建遵循了 Apple’s iOS design language 的界面。如何更新Widgets?
在 iOS 上更新 views,只需要直接改變它們就可以了。在 Flutter 中,widgets 是不可變的,而且不能被直接更新。你需要去操縱 widget 的 state。這也正是有狀態(tài)的和無狀態(tài)的 widget 這一概念的來源。一個(gè) StatelessWidget 正如它聽起來一樣,是一個(gè)沒有附加狀態(tài)的 widget。
StatelessWidget 在你構(gòu)建初始化后不再進(jìn)行改變的界面時(shí)非常有用。然而在數(shù)據(jù)進(jìn)行更改的時(shí)候,使用StatefulWidget 擁有一個(gè) State 對象來存儲(chǔ)它的狀態(tài)數(shù)據(jù),并在 widget 樹重建時(shí)攜帶著它,因此狀態(tài)不會(huì)丟失。
例如下方是一個(gè)靜態(tài)的 StatelessWidget:
Text(
'I like Flutter!',
style: TextStyle(fontWeight: FontWeight.bold),
);
類似一個(gè)固定的Label并且?guī)в泄潭▋?nèi)容的Label.
帶有事件更新的Widget的如下代碼所示
class SampleApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Sample App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SampleAppPage(),
);
}
}
class SampleAppPage extends StatefulWidget {
SampleAppPage({Key key}) : super(key: key);
@override
_SampleAppPageState createState() => _SampleAppPageState();
}
class _SampleAppPageState extends State<SampleAppPage> {
// Default placeholder text
String textToShow = "I Like Flutter";
void _updateText() {
setState(() {
// update the text
textToShow = "Flutter is Awesome!";
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Sample App"),
),
body: Center(child: Text(textToShow)),
floatingActionButton: FloatingActionButton(
onPressed: _updateText,
tooltip: 'Update Text',
child: Icon(Icons.update),
),
);
}
}
由于Widget是不可以動(dòng)態(tài)進(jìn)行改變的,所以在創(chuàng)建Widget的時(shí)候,傳入一個(gè)Type值或者Boolean值, 進(jìn)行創(chuàng)建不同類型的Widget, 來動(dòng)態(tài)的顯示不同的視圖.然而在Widget中body可以加入不同的padding數(shù)據(jù), 類似于XIB | Storyboard中的約束.
在 iOS 中,什么東西都會(huì)有一個(gè) .opacity 或是 .alpha 的屬性。在 Flutter 中,你需要給 widget 包裹一個(gè) Opacity widget 來做到這一點(diǎn)。
針對繪圖, Flutter提供了Canvas繪圖的一套API.線程和同步
Dart是單線程執(zhí)行模式,但是它支持Isolate(一種讓Dart代碼運(yùn)行在其他線程上的方式) Flutter的Event loop 與 iOS中的main loop 相似 Looper是附加在主線程上的.
Dart 的單線程模型并不意味著你寫的代碼一定是阻塞操作,從而卡住 UI。相反,使用 Dart 語言提供的異步工具,例如 async / await ,來實(shí)現(xiàn)異步操作。
舉個(gè)例子,你可以使用 async / await 來讓 Dart 幫你做一些繁重的工作,編寫網(wǎng)絡(luò)請求代碼而不會(huì)掛起 UI:
loadData() async {
String dataURL = "https://jsonplaceholder.typicode.com/posts";
http.Response response = await http.get(dataURL);
setState(() {
widgets = json.decode(response.body);
});
}
一旦 await 到網(wǎng)絡(luò)請求完成,通過調(diào)用 setState() 來更新 UI,這會(huì)觸發(fā) widget 子樹的重建,并更新相關(guān)數(shù)據(jù)。
下面的例子展示了異步加載數(shù)據(jù),并用 ListView 列表渲染展示出來:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() {
runApp(SampleApp());
}
class SampleApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Sample App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SampleAppPage(),
);
}
}
class SampleAppPage extends StatefulWidget {
SampleAppPage({Key key}) : super(key: key);
@override
_SampleAppPageState createState() => _SampleAppPageState();
}
class _SampleAppPageState extends State<SampleAppPage> {
List widgets = [];
@override
void initState() {
super.initState();
loadData();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Sample App"),
),
body: ListView.builder(
itemCount: widgets.length,
itemBuilder: (BuildContext context, int position) {
return getRow(position);
}));
}
Widget getRow(int i) {
return Padding(
padding: EdgeInsets.all(10.0),
child: Text("Row ${widgets[i]["title"]}")
);
}
loadData() async {
String dataURL = "https://jsonplaceholder.typicode.com/posts";
http.Response response = await http.get(dataURL);
setState(() {
widgets = json.decode(response.body);
});
}
}