自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

寫(xiě)給前端工程師的Flutter詳細(xì)教程

新聞 前端
最愛(ài)折騰的就是前端工程師了,從 jQuery 折騰到 AngularJs,再折騰到 Vue、React。最愛(ài)跨屏的也是前端工程師,從 phonegap,折騰到 React Native,這不又折騰到了 Flutter。

最愛(ài)折騰的就是前端工程師了,從 jQuery 折騰到 AngularJs,再折騰到 Vue、React。最愛(ài)跨屏的也是前端工程師,從 phonegap,折騰到 React Native,這不又折騰到了 Flutter。

圖啥?

低成本地為用戶帶來(lái)更優(yōu)秀的用戶體驗(yàn)。

目前來(lái)說(shuō)Flutter可能是其中最優(yōu)秀的一種方案了。 

Flutter 是什么?

Flutter is Google’s UI toolkit for building beautiful, natively compiled applications for mobile, web, and desktop from a single codebase.

Flutter是由原 Google Chrome 團(tuán)隊(duì)成員,利用 Chrome 2D 渲染引擎,然后精簡(jiǎn) CSS 布局演變而來(lái)。

写给前端工程师的 Flutter 详细教程

或者更詳細(xì)的版本

写给前端工程师的 Flutter 详细教程

  • Flutter 在各個(gè)原生的平臺(tái)中,使用自己的 C++的引擎渲染界面,沒(méi)有使用 webview,也不像 RN、NativeScript 一樣使用系統(tǒng)的組件。簡(jiǎn)單來(lái)說(shuō)平臺(tái)只是給 Flutter 提供一個(gè)畫(huà)布。
  • 界面使用 Dart 語(yǔ)言開(kāi)發(fā),貌似唯一支持 JIT,和 AOT 模式的強(qiáng)類型語(yǔ)言。
  • 寫(xiě)法非常的現(xiàn)代,聲明式,組件化,Composition > inheritance,響應(yīng)式……就是現(xiàn)在前端流行的這一套 😄
  • 一套代碼搞定所有平臺(tái)。

Flutter 為什么快?Flutter 相比 RN 的優(yōu)勢(shì)在哪里?

從架構(gòu)中實(shí)際上已經(jīng)能看出 Flutter 為什么快,至少相比之前的當(dāng)紅炸子雞 React Native 快的原因了。

  • Skia 引擎,Chrome, Chrome OS,Android,F(xiàn)irefox,F(xiàn)irefox OS 都以此作為渲染引擎。
  • Dart 語(yǔ)言可以 AOT 編譯成 ARM Code,讓布局以及業(yè)務(wù)代碼運(yùn)行的最快,而且 Dart 的 GC 針對(duì) Flutter 頻繁銷毀創(chuàng)建 Widget 做了專門(mén)的優(yōu)化。
  • CSS 的的子集 Flex like 的布局方式,保留強(qiáng)大表現(xiàn)能力的同時(shí),也保留了性能。
  • Flutter 業(yè)務(wù)書(shū)寫(xiě)的 Widget 在渲染之前 diff 轉(zhuǎn)化成 Render Object,對(duì),就像 React 中的 Virtual DOM,以此來(lái)確保開(kāi)發(fā)體驗(yàn)和性能。

而相比 React Native:

  • RN 使用 JavaScript 來(lái)運(yùn)行業(yè)務(wù)代碼,然后 JS Bridge 的方式調(diào)用平臺(tái)相關(guān)組件,性能比有損失,甚至平臺(tái)不同 js 引擎都不一樣。
  • RN 使用平臺(tái)組件,行為一致性會(huì)有打折,或者說(shuō),開(kāi)發(fā)者需要處理更多平臺(tái)相關(guān)的問(wèn)題。

而具體兩者的性能測(cè)試,可以看這里,結(jié)論是 Flutter,在 CPU,F(xiàn)PS,內(nèi)存穩(wěn)定上均優(yōu)于 ReactNative。

Dart 語(yǔ)言

在開(kāi)始 Flutter 之前,我們需要先了解下 Dart 語(yǔ)言……

Dart 是由 Google 開(kāi)發(fā),最初是想作為 JavaScript 替代語(yǔ)言,但是失敗沉寂之后,作為 Flutter 獨(dú)有開(kāi)發(fā)語(yǔ)言又煥發(fā)了第二春 😂。

實(shí)際上即使到了 2.0,Dart 語(yǔ)法和 JavaScriptFlutter非常的相像。單線程,Event Loop……

写给前端工程师的 Flutter 详细教程

當(dāng)然作為一篇寫(xiě)給前端工程師的教程,我在這里只想寫(xiě)寫(xiě) JavaScript 中暫時(shí)沒(méi)有的,Dart 中更為省心,也更“甜”的東西。

  • 不會(huì)飄的this
  • 強(qiáng)類型,當(dāng)然前端現(xiàn)在有了 TypeScript 😬
  • 強(qiáng)大方便的操作符號(hào):
  • ?. 方便安全的foo?.bar取值,如果 foo 為null,那么取值為null
  • ?? condition ? expr1 : expr2 可以簡(jiǎn)寫(xiě)為expr1 ?? expr2
  • =和其他符號(hào)的組合: *=、~/=、&=、|= ……
  • 級(jí)聯(lián)操作符(Cascade notation ..)
  1. // 想想這樣省了多少變量聲明  
  2. querySelect('#button')  
  3.  ..text ="Confirm"  
  4.  ..classes.add('important')  
  5.  ..onClick.listen((e) => window.alert('Confirmed'))  

甚至可以重寫(xiě)操作符

  1. class Vector { 
  2.   final int x, y; 
  3.   Vector(this.x, this.y); 
  4.  
  5.   Vector operator +(Vector v) => Vector(x + v.x, y + v.y); 
  6.   Vector operator -(Vector v) => Vector(x - v.x, y - v.y); 
  7.  
  8.   // Operator == and hashCode not shown. For details, see note below. 
  9.   // ··· 
  10.  
  11. void main() { 
  12.   final v = Vector(23); 
  13.   final w = Vector(22); 
  14.  
  15.   assert(v + w == Vector(45)); 
  16.   assert(v - w == Vector(01)); 

注:重寫(xiě)==,也需要重寫(xiě) Object hashCodegetter

  1. class Person { 
  2.   final String firstName, lastName; 
  3.   Person(this.firstName, this.lastName); 
  4.  
  5.   // Override hashCode using strategy from Effective Java, 
  6.   // Chapter 11. 
  7.   @override 
  8.   int get hashCode { 
  9.     int result = 17
  10.     result = 37 * result + firstName.hashCode; 
  11.     result = 37 * result + lastName.hashCode; 
  12.     return result; 
  13.   } 
  14.  
  15.   // You should generally implement operator == if you 
  16.   // override hashCode. 
  17.   @override 
  18.   bool operator ==(dynamic other) { 
  19.     if (other is! Person) return false
  20.     Person person = other; 
  21.     return (person.firstName == firstName && 
  22.         person.lastName == lastName); 
  23.   } 
  24.  
  25. void main() { 
  26.   var p1 = Person('Bob''Smith'); 
  27.   var p2 = Person('Bob''Smith'); 
  28.   var p3 = 'not a person'
  29.   assert(p1.hashCode == p2.hashCode); 
  30.   assert(p1 == p2); 
  31.   assert(p1 != p3); 

這點(diǎn)在 diff 對(duì)象的時(shí)候尤其有用。

lsolate

Dart 運(yùn)行在獨(dú)立隔離的 iSolate 中就類似 JavaScript 一樣,單線程事件驅(qū)動(dòng),但是 Dart 也開(kāi)放了創(chuàng)建其他 isolate,充分利用 CPU 的多和能力。

  1. loadData() async { 
  2.    // 通過(guò)spawn新建一個(gè)isolate,并綁定靜態(tài)方法 
  3.    ReceivePort receivePort =ReceivePort(); 
  4.    await Isolate.spawn(dataLoader, receivePort.sendPort); 
  5.    // 獲取新isolate的監(jiān)聽(tīng)port 
  6.    SendPort sendPort = await receivePort.first; 
  7.    // 調(diào)用sendReceive自定義方法 
  8.    List dataList = await sendReceive(sendPort, 'https://hicc.me/posts'); 
  9.    print('dataList $dataList'); 
  10.  
  11. // isolate的綁定方法 
  12. static dataLoader(SendPort sendPort) async{ 
  13.    // 創(chuàng)建監(jiān)聽(tīng)port,并將sendPort傳給外界用來(lái)調(diào)用 
  14.    ReceivePort receivePort =ReceivePort(); 
  15.    sendPort.send(receivePort.sendPort); 
  16.  
  17.    // 監(jiān)聽(tīng)外界調(diào)用 
  18.    await for (var msg in receivePort) { 
  19.      String requestURL =msg[0]; 
  20.      SendPort callbackPort =msg[1]; 
  21.  
  22.      Client client = Client(); 
  23.      Response response = await client.get(requestURL); 
  24.      List dataList = json.decode(response.body); 
  25.      // 回調(diào)返回值給調(diào)用者 
  26.      callbackPort.send(dataList); 
  27.   }     
  28.  
  29. // 創(chuàng)建自己的監(jiān)聽(tīng)port,并且向新isolate發(fā)送消息 
  30. Future sendReceive(SendPort sendPort, String url) { 
  31.    ReceivePort receivePort =ReceivePort(); 
  32.    sendPort.send([url, receivePort.sendPort]); 
  33.    // 接收到返回值,返回給調(diào)用者 
  34.    return receivePort.first; 

當(dāng)然 Flutter 中封裝了compute,可以方便的使用,譬如在其它 isolate 中解析大的 json。

Dart UI as Code

在這里單獨(dú)提出來(lái)的意義在于,從 React 開(kāi)始,到 Flutter,到最近的 Apple SwiftUI,Android Jetpack Compose 聲明式組件寫(xiě)法越發(fā)流行,Web 前端使用 JSX 來(lái)讓開(kāi)發(fā)者更方便的書(shū)寫(xiě),而 Flutter,SwiftUI 則直接從優(yōu)化語(yǔ)言本身著手。

函數(shù)類的命名參數(shù)

  1. void test({@required int age,String name}) { 
  2.   print(name); 
  3.   print(age); 
  4. // 解決函數(shù)調(diào)用時(shí)候,參數(shù)不明確的問(wèn)題 
  5. test(name:"hicc",age: 30
  6. // 這樣對(duì)于組件的使用尤為方便 
  7. class MyApp extends StatelessWidget { 
  8.   @override 
  9.   Widget build(BuildContext context) { 
  10.   return Scaffold( 
  11.       appBar: AppBar(), 
  12.       body: Container(), 
  13.       floatingActionButton:FloatingActionButton() 
  14.     ); 
  15.   } 

大殺器:Collection If 和 Collection For

  1. // collection If 
  2. Widget build(BuildContext context) { 
  3.   return Row( 
  4.     children: [ 
  5.       IconButton(icon: Icon(Icons.menu)), 
  6.       Expanded(child: title), 
  7.       if (!isAndroid) 
  8.         IconButton(icon: Icon(Icons.search)), 
  9.     ], 
  10.   ); 
  11. // Collect For 
  12. var command = [ 
  13.   engineDartPath, 
  14.   frontendServer, 
  15.   for (var root in fileSystemRoots) "--filesystem-root=$root"
  16.   for (var entryPoint in entryPoints) 
  17.     if (fileExists("lib/$entryPoint.json")) "lib/$entryPoint"
  18.   mainPath 
  19. ]; 

更多 Dart 2.3 對(duì)此的優(yōu)化看這里。

Flutter 怎么寫(xiě)

到這里終于到正題了,如果熟悉 web 前端,熟悉 React 的話,你會(huì)對(duì)下面要講的異常的熟悉。

写给前端工程师的 Flutter 详细教程

Flutter App 的一切從lib/main.dart文件的 main 函數(shù)開(kāi)始:

  1. import 'package:flutter/material.dart'
  2. void main() => runApp(MyApp()); 
  3.  
  4. class MyApp extends StatelessWidget { 
  5.   @override 
  6.   Widget build(BuildContext context) { 
  7.     return MaterialApp( 
  8.       title: 'Welcome to Flutter'
  9.       home: Scaffold( 
  10.         appBar: AppBar( 
  11.           title: Text('Welcome to Flutter'), 
  12.         ), 
  13.         body: Center( 
  14.           child: Text('Hello World'), 
  15.         ), 
  16.       ), 
  17.     ); 
  18.   } 

Dart 類 build 方法返回的便是 Widget,在 Flutter 中一切都是 Widget,包括但不限于

  • 結(jié)構(gòu)性元素,menu,button 等
  • 樣式類元素,font,color 等
  • 布局類元素,padding,margin 等
  • 導(dǎo)航
  • 手勢(shì)

Widget 是 Dart 中特殊的類,通過(guò)實(shí)例化(Dart 中new 是可選的)相互嵌套,你的這個(gè) App 就是形如下圖的一顆組件樹(shù)(Dart 入口函數(shù)的概念,main.dart -> main())。

写给前端工程师的 Flutter 详细教程

Widget 布局

上說(shuō)過(guò) Flutter 布局思路來(lái)自 CSS,而 Flutter 中一切皆 Widget,因此整體布局也很簡(jiǎn)單:

  • 容器組件 Container
  • decoration 裝飾屬性,設(shè)置背景色,背景圖,邊框,圓角,陰影和漸變等
  • margin
  • padding
  • alignment
  • width
  • height
  • Padding,Center
  • Row,Column,Flex
  • Wrap, Flow 流式布局
  • Stack, Z 軸布局
  • ……

Flutter 中 Widget 可以分為三類,形如 React 中“展示組件”、“容器組件”,“context”。

StatelessWidget

這個(gè)就是 Flutter 中的“展示組件”,自身不保存狀態(tài),外部參數(shù)變化就銷毀重新創(chuàng)建。Flutter 建議盡量使用無(wú)狀態(tài)的組件。

StatefulWidget

狀態(tài)組件就是類似于 React 中的“容器組件”了,F(xiàn)lutter 中狀態(tài)組件寫(xiě)法會(huì)稍微不一樣。

  1. class Counter extends StatefulWidget {  
  2.   // This class is the configuration for the state. It holds the  
  3.   // values (in this case nothing) provided by the parent and used by the build  
  4.   // method of the State. Fields in a Widget subclass are always marked "final".  
  5.   @override  
  6.   _CounterState createState() => _CounterState();  
  7. }  
  8.   
  9. class _CounterState extends State<Counter> {  
  10.   int _counter = 0;  
  11.   
  12.   void _increment() {  
  13.     setState(() {  
  14.       // This call to setState tells the Flutter framework that  
  15.       // something has changed in this State, which causes it to rerun  
  16.       // the build method below so that the display can reflect the  
  17.       // updated values. If you change _counter without calling  
  18.       // setState(), then the build method won't be called again,  
  19.       // and so nothing would appear to happen.  
  20.       _counter++;  
  21.     });  
  22.   }  
  23.   
  24.   @override  
  25.   Widget build(BuildContext context) {  
  26.     // This method is rerun every time setState is called, for instance  
  27.     // as done by the _increment method above.  
  28.     // The Flutter framework has been optimized to make rerunning  
  29.     // build methods fast, so that you can just rebuild anything that  
  30.     // needs updating rather than having to individually change  
  31.     // instances of widgets.  
  32.     return Row(  
  33.       children: <Widget>[  
  34.         RaisedButton(  
  35.           onPressed: _increment,  
  36.           child: Text('Increment'),  
  37.         ),  
  38.         Text('Count: $_counter'),  
  39.       ],  
  40.     );  
  41.   }  
  42. }  

可以看到 Flutter 中直接使用了和 React 中同名的setState方法,不過(guò)不會(huì)有變量合并的東西,當(dāng)然也有生命周期。

写给前端工程师的 Flutter 详细教程

可以看到一個(gè)有狀態(tài)的組件需要兩個(gè) Class,這樣寫(xiě)的原因在于,F(xiàn)lutter 中 Widget 都是 immmutable 的,狀態(tài)組件的狀態(tài)保存在 State 中,組件仍然每次重新創(chuàng)建,Widget 在這里只是一種對(duì)組件的描述,F(xiàn)lutter 會(huì) diff 轉(zhuǎn)換成 Element,然后轉(zhuǎn)換成 RenderObject 才渲染。

写给前端工程师的 Flutter 详细教程

Flutter Widget 更多的渲染流程可以看這里。

實(shí)際上 Widget 只是作為組件結(jié)構(gòu)一種描述,還可以帶來(lái)的好處是,你可以更方便的做一些主題性的組件, Flutter 官方提供的Material Components widgets和Cupertino (iOS-style) widgets質(zhì)量就相當(dāng)高,再配合 Flutter 亞秒級(jí)的Hot Reload,開(kāi)發(fā)體驗(yàn)可以說(shuō)挺不錯(cuò)的。

State Management

setState()可以很方便的管理組件內(nèi)的數(shù)據(jù),但是 Flutter 中狀態(tài)同樣是從上往下流轉(zhuǎn)的,因此也會(huì)遇到和 React 中同樣的問(wèn)題,如果組件樹(shù)太深,逐層狀態(tài)創(chuàng)建就顯得很麻煩了,更不要說(shuō)代碼的易讀和易維護(hù)性了。

InheritedWidget

同樣 Flutter 也有個(gè)context一樣的東西,那就是InheritedWidget,使用起來(lái)也很簡(jiǎn)單。

  1. class GlobalData extends InheritedWidget { 
  2.   final int count; 
  3.   GlobalData({Key key, this.count,Widget child}):super(key:key,child:child); 
  4.   @override 
  5.   bool updateShouldNotify(GlobalData oldWidget) { 
  6.     return oldWidget.count != count; 
  7.   } 
  8.  
  9.   static GlobalData of(BuildContext context) => context.inheritFromWidgetOfExactType(GlobalData); 
  10.  
  11. class MyApp extends StatelessWidget { 
  12.   // This widget is the root of your application. 
  13.   @override 
  14.   Widget build(BuildContext context) { 
  15.     return MaterialApp( 
  16.       title: 'Flutter Demo'
  17.       theme: ThemeData( 
  18.         primarySwatch: Colors.blue, 
  19.       ), 
  20.       home: MyHomePage(title: 'Flutter Demo Home Page'), 
  21.     ); 
  22.   } 
  23.  
  24. class MyHomePage extends StatefulWidget { 
  25.   MyHomePage({Key key, this.title}) : super(key: key); 
  26.  
  27.   final String title; 
  28.  
  29.   @override 
  30.   _MyHomePageState createState() => _MyHomePageState(); 
  31.  
  32. class _MyHomePageState extends State<MyHomePage> { 
  33.   int _counter = 0
  34.  
  35.   void _incrementCounter() { 
  36.       _counter++; 
  37.     }); 
  38.   } 
  39.  
  40.   @override 
  41.   Widget build(BuildContext context) { 
  42.     return Scaffold( 
  43.       appBar: AppBar( 
  44.         title: Text(widget.title), 
  45.       ), 
  46.       body: GlobalData( 
  47.         count: _counter, 
  48.         child: Center( 
  49.           child: Column( 
  50.             mainAxisAlignment: MainAxisAlignment.center, 
  51.             children: <Widget>[ 
  52.               Text( 
  53.                 'You have pushed the button this many times:'
  54.               ), 
  55.               Text( 
  56.                 '$_counter'
  57.                 style: Theme.of(context).textTheme.display1, 
  58.               ), 
  59.               Body(), 
  60.               Body2() 
  61.             ], 
  62.           ), 
  63.         ), 
  64.       ), 
  65.       floatingActionButton: FloatingActionButton( 
  66.         onPressed: _incrementCounter, 
  67.         tooltip: 'Increment'
  68.         child: Icon(Icons.add), 
  69.       ), 
  70.     ); 
  71.   } 
  72.  
  73. class Body extends StatelessWidget { 
  74.   @override 
  75.   Widget build(BuildContext context) { 
  76.     GlobalData globalData = GlobalData.of(context); 
  77.     return Text(globalData.count.toString()); 
  78.   } 
  79.  
  80. class Body2 extends StatelessWidget { 
  81.   @override 
  82.   Widget build(BuildContext context) { 
  83.     // TODO: implement build 
  84.     GlobalData globalData = GlobalData.of(context); 
  85.     return Text(globalData.count.toString()); 
  86.   } 

具體實(shí)現(xiàn)原理可以參考這里,不過(guò) Google 封裝了一個(gè)更為上層的庫(kù)provider,具體使用可以看這里。

BlOC

BlOC是 Flutter team 提出建議的另一種更高級(jí)的數(shù)據(jù)組織方式,也是我最中意的方式。簡(jiǎn)單來(lái)說(shuō):

Bloc = InheritedWidget + RxDart(Stream)

Dart 語(yǔ)言中內(nèi)置了 Steam,Stream ~= Observable,配合RxDart, 然后加上StreamBuilder會(huì)是一種異常強(qiáng)大和自由的模式。

  1. class GlobalData extends InheritedWidget { 
  2.   final int count; 
  3.   final Stream<String> timeInterval$ = new Stream.periodic(Duration(seconds: 10)).map((time) => new DateTime.now().toString()); 
  4.   GlobalData({Key key, this.count,Widget child}):super(key:key,child:child); 
  5.   @override 
  6.   bool updateShouldNotify(GlobalData oldWidget) { 
  7.     return oldWidget.count != count; 
  8.   } 
  9.  
  10.   static GlobalData of(BuildContext context) => context.inheritFromWidgetOfExactType(GlobalData); 
  11.  
  12.  
  13. class TimerView extends StatelessWidget { 
  14.  
  15.   @override 
  16.   Widget build(BuildContext context) { 
  17.     GlobalData globalData = GlobalData.of(context); 
  18.     return StreamBuilder( 
  19.         stream: globalData.timeInterval$, 
  20.         builder: (context, snapshot) { 
  21.           return Text(snapshot?.data ?? ''); 
  22.         } 
  23.     ); 
  24.   } 

當(dāng)然 Bloc 的問(wèn)題在于

  • 學(xué)習(xí)成本略高,Rx 的概念要吃透,不然你會(huì)抓狂
  • 自由帶來(lái)的問(wèn)題是,可能代碼不如 Redux 類的規(guī)整。

順便,今年 Apple 也擁抱了響應(yīng)式,Combine(Rx like) + SwiftUI 也基本等于 Bloc 了。

所以,Rx 還是要趕緊學(xué)起來(lái) 😬

除去 Bloc,F(xiàn)lutter 中還是可以使用其他的方案,譬如:

  • Flutter Redux
  • 阿里閑魚(yú)的Fish Redux,據(jù)說(shuō)性能很好。
  • Mobx
  • ……

展開(kāi)來(lái)說(shuō)現(xiàn)在的前端開(kāi)發(fā)使用強(qiáng)大的框架頁(yè)面組裝已經(jīng)不是難點(diǎn)了。開(kāi)發(fā)的難點(diǎn)在于如何組合富交互所需的數(shù)據(jù),也就是上面圖中的state部分。

更具體來(lái)說(shuō),是怎么優(yōu)雅,高效,易維護(hù)地處理短暫數(shù)據(jù)(ephemeral state)setState()和需要共享的 App State 的問(wèn)題,這是個(gè)工程性的問(wèn)題,但往往也是日常開(kāi)發(fā)最難的事情了,引用 Redux 作者 Dan 的一句:

“The rule of thumb is:Do whatever is less awkward.”

到這里,主要的部分已經(jīng)講完了,有這些已經(jīng)可以開(kāi)發(fā)出一個(gè)不錯(cuò)的 App 了。剩下的就當(dāng)成一個(gè) bonus 吧。

測(cè)試

Flutter debugger,測(cè)試都是出場(chǎng)自帶,用起來(lái)也不難。

  1. // 測(cè)試在/test/目錄下面 
  2. void main() { 
  3.   testWidgets('Counter increments smoke test', (WidgetTester tester) async { 
  4.     // Build our app and trigger a frame. 
  5.     await tester.pumpWidget(MyApp()); 
  6.  
  7.     // Verify that our counter starts at 0. 
  8.     expect(find.text('0'), findsOneWidget); 
  9.     expect(find.text('1'), findsNothing); 
  10.  
  11.     // Tap the '+' icon and trigger a frame. 
  12.     await tester.tap(find.byIcon(Icons.add)); 
  13.     await tester.pump(); 
  14.  
  15.     // Verify that our counter has incremented. 
  16.     expect(find.text('0'), findsNothing); 
  17.     expect(find.text('1'), findsOneWidget); 
  18.   }); 

包管理,資源管理

類似與 JavaScript 的 npm,F(xiàn)lutter,也就是 Dart 也有自己的包倉(cāng)庫(kù)。不過(guò)項(xiàng)目包的依賴使用 yaml 文件來(lái)描述:

  1. name: app 
  2. description: A new Flutter project. 
  3. version: 1.0.0+1 
  4. environment: 
  5.   sdk: ">=2.1.0 <3.0.0" 
  6.  
  7. dependencies: 
  8.   flutter: 
  9.     sdk: flutter 
  10.  
  11.   cupertino_icons: ^0.1.2 

生命周期

移動(dòng)應(yīng)用總歸需要應(yīng)用級(jí)別的生命周期,flutter 中使用生命周期鉤子,也非常的簡(jiǎn)單:

  1. class MyApp extends StatefulWidget { 
  2.   @override 
  3.   _MyAppState createState() => new _MyAppState(); 
  4. class _MyAppState extends State<MyApp> with WidgetsBindingObserver { 
  5.   @override 
  6.   void initState() { 
  7.     super.initState(); 
  8.     WidgetsBinding.instance.addObserver(this); 
  9.   } 
  10.  
  11.   @override 
  12.   void dispose() { 
  13.     WidgetsBinding.instance.removeObserver(this); 
  14.     super.dispose(); 
  15.   } 
  16.  
  17.   @override 
  18.   void didChangeAppLifecycleState(AppLifecycleState state) { 
  19.     switch (state) { 
  20.       case AppLifecycleState.inactive: 
  21.         print('AppLifecycleState.inactive'); 
  22.         break
  23.       case AppLifecycleState.paused: 
  24.         print('AppLifecycleState.paused'); 
  25.         break
  26.       case AppLifecycleState.resumed: 
  27.         print('AppLifecycleState.resumed'); 
  28.         break
  29.       case AppLifecycleState.suspending: 
  30.         print('AppLifecycleState.suspending'); 
  31.         break
  32.     } 
  33.     super.didChangeAppLifecycleState(state); 
  34.   } 
  35.  
  36.   @override 
  37.   Widget build(BuildContext context) { 
  38.       return Container(); 
  39.   } 

使用原生能力

和 ReactNative 類似,F(xiàn)lutter 也是使用類似事件的機(jī)制來(lái)使用平臺(tái)相關(guān)能力。

写给前端工程师的 Flutter 详细教程

Flutter Web, Flutter Desktop

這些還在開(kāi)發(fā)當(dāng)中,鑒于對(duì) Dart 喜歡,以及對(duì) Flutter 性能的樂(lè)觀,這些倒是很值得期待。

写给前端工程师的 Flutter 详细教程  

 

責(zé)任編輯:張燕妮 來(lái)源: 騰訊技術(shù)工程
相關(guān)推薦

2019-07-29 16:05:48

前端DockerNode.js

2019-01-21 15:52:02

前端工程師Flutter代碼

2015-05-07 14:08:26

初學(xué)前端工程師

2015-08-26 14:18:25

Web前端工程師價(jià)值

2015-09-30 10:25:03

前端工程師

2019-09-27 14:33:34

2018-08-17 15:33:37

2019-03-22 10:10:44

AndroidiOS移動(dòng)系統(tǒng)

2018-11-15 15:55:44

前端工程師Web云計(jì)算

2010-01-13 10:53:51

Web前端工程師定位

2009-03-20 10:24:38

網(wǎng)絡(luò)工程師數(shù)據(jù)庫(kù)計(jì)算機(jī)信息系統(tǒng)

2014-12-23 14:55:23

前端

2016-09-22 16:14:45

前端設(shè)計(jì)Photoshop

2010-01-13 10:10:07

Web前端工程師

2015-03-16 16:01:40

Web前端前端工程師Web

2019-06-24 09:40:17

前端前端工程師開(kāi)發(fā)工具

2012-09-07 10:20:53

2012-06-28 14:23:32

Web

2019-10-29 16:29:28

運(yùn)維架構(gòu)開(kāi)發(fā)

2022-08-08 15:45:44

JavaPromise前端
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)