鍐欑粰鍓嶇宸ョ▼甯堢殑 Flutter 鏁欑▼

Posted 鍥鹃泙绀惧尯

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了鍐欑粰鍓嶇宸ョ▼甯堢殑 Flutter 鏁欑▼相关的知识,希望对你有一定的参考价值。


w鏈枃鐢卞浘闆€绀惧尯璁よ瘉浣滆€?nbsp;Tyler 鍐欎綔鑰屾垚锛岋紝鐐瑰嚮闃呰鍘熸枃鏌ョ湅浣滆€呯殑鍗氬閾炬帴锛屾劅璋綔鑰呯殑浼樿川杈撳嚭锛岃鎴戜滑鐨勬妧鏈笘鐣屽彉寰楁洿鍔犵編濂金煒?/p>

娑夊強Dart璇█锛孎lutter鍘熺悊锛孎lutter Widget锛屼互鍙奆lutter涓殑鐘舵€佺鐞嗘柟妗堢瓑锛屽牚绉版渶鍏ㄧ殑Flutter鏁欑▼馃槃

鏈€鐖辨姌鑵剧殑灏辨槸鍓嶇宸ョ▼甯堜簡锛屼粠 jQuery 鎶樿吘鍒?AngularJs锛屽啀鎶樿吘鍒?Vue銆丷eact銆傛渶鐖辫法绔殑涔熸槸鍓嶇宸ョ▼甯堬紝浠?phonegap锛屾姌鑵惧埌 React Native锛岃繖涓嶅張鎶樿吘鍒颁簡 Flutter銆傚浘鍟ワ紵浣庢垚鏈?/strong>鍦颁负鐢ㄦ埛甯︽潵鏇翠紭绉€鐨勭敤鎴蜂綋楠?/strong>銆傜洰鍓嶆潵璇?span class="mq-10">Flutter[1]鍙兘鏄叾涓渶浼樼鐨勪竴绉嶆柟妗堜簡銆?/p>

Flutter 鏄粈涔堬紵

Flutter is Google鈥檚 UI toolkit for building beautiful, natively compiled applications for mobile[2], web[3], and desktop[4] from a single codebase.

Flutter[5]鏄敱鍘?Google Chrome 鍥㈤槦鎴愬憳锛屽埄鐢?Chrome 2D 娓叉煋寮曟搸锛岀劧鍚庣簿绠€ CSS 甯冨眬婕斿彉鑰屾潵銆?img data-ratio="0.517774343122102" src="/img?url=https://mmbiz.qpic.cn/mmbiz_png/gEz4yUa4ueSV30picZ75OH9icA4920FUsicX5icbrzT629hF3WkickcTibtn5FOtNxsVPmHw5qwgrgyFBeZ1kUZxicp2A/640?wx_fmt=png" data-type="png" data-w="1294" alt="鍐欑粰鍓嶇宸ョ▼甯堢殑 Flutter 鏁欑▼" class="mq-25">鎴栬€呮洿璇︾粏鐨勭増鏈?img data-ratio="0.5247469066366705" src="/img?url=https://mmbiz.qpic.cn/mmbiz_png/gEz4yUa4ueSV30picZ75OH9icA4920FUsicqr1Xpn9qOrFSY7po1MuGcwiamZ5HzxpbMMQxF9ZlgsmnRkia47D9PShA/640?wx_fmt=png" data-type="png" data-w="3556" alt="鍐欑粰鍓嶇宸ョ▼甯堢殑 Flutter 鏁欑▼" class="mq-26">

  • Flutter 鍦ㄥ悇涓師鐢熺殑骞冲彴涓紝浣跨敤鑷繁鐨?C++鐨勫紩鎿庢覆鏌撶晫闈紝娌℃湁浣跨敤 webview锛屼篃涓嶅儚 RN銆丯ativeScript 涓€鏍蜂娇鐢ㄧ郴缁熺殑缁勪欢銆傜畝鍗曟潵璇村钩鍙板彧鏄粰 Flutter 鎻愪緵涓€涓敾甯冦€?
  • 鐣岄潰浣跨敤 Dart 璇█寮€鍙戯紝璨屼技鍞竴鏀寔 JIT锛屽拰 AOT 妯″紡鐨勫己绫诲瀷璇█銆?
  • 鍐欐硶闈炲父鐨勭幇浠o紝澹版槑寮忥紝缁勪欢鍖栵紝Composition > inheritance锛屽搷搴斿紡鈥︹€﹀氨鏄幇鍦ㄥ墠绔祦琛岀殑杩欎竴濂?馃槃
  • 涓€濂椾唬鐮佹悶瀹氭墍鏈夊钩鍙般€?

Flutter 涓轰粈涔堝揩锛烣lutter 鐩告瘮 RN 鐨勪紭鍔垮湪鍝噷锛?/h2>

浠庢灦鏋勪腑瀹為檯涓婂凡缁忚兘鐪嬪嚭 Flutter 涓轰粈涔堝揩锛岃嚦灏戠浉姣斾箣鍓嶇殑褰撶孩鐐稿瓙楦?React Native 蹇殑鍘熷洜浜嗐€?/p>

  • Skia 寮曟搸锛孋hrome锛?Chrome OS锛孉ndroid锛孎irefox锛孎irefox OS 閮戒互姝や綔涓烘覆鏌撳紩鎿庛€?
  • Dart 璇█鍙互 AOT 缂栬瘧鎴?ARM Code锛岃甯冨眬浠ュ強涓氬姟浠g爜杩愯鐨勬渶蹇紝鑰屼笖 Dart 鐨?GC 閽堝 Flutter 棰戠箒閿€姣佸垱寤?Widget 鍋氫簡涓撻棬鐨勪紭鍖栥€?
  • CSS 鐨勭殑瀛愰泦 Flex like 鐨勫竷灞€鏂瑰紡锛屼繚鐣欏己澶ц〃鐜拌兘鍔涚殑鍚屾椂锛屼篃淇濈暀浜嗘€ц兘銆?
  • Flutter 涓氬姟涔﹀啓鐨?Widget 鍦ㄦ覆鏌撲箣鍓?diff 杞寲鎴?Render Object锛屽锛屽氨鍍?React 涓殑 Virtual DOM锛屼互姝ゆ潵纭繚寮€鍙戜綋楠屽拰鎬ц兘銆?

鑰岀浉姣?React Native锛?/p>

  • RN 浣跨敤 javascript 鏉ヨ繍琛屼笟鍔′唬鐮侊紝鐒跺悗 JS Bridge 鐨勬柟寮忚皟鐢ㄥ钩鍙扮浉鍏崇粍浠讹紝鎬ц兘姣旀湁鎹熷け锛岀敋鑷冲钩鍙颁笉鍚?js 寮曟搸閮戒笉涓€鏍枫€?
  • RN 浣跨敤骞冲彴缁勪欢锛岃涓轰竴鑷存€т細鏈夋墦鎶橈紝鎴栬€呰锛屽紑鍙戣€呴渶瑕佸鐞嗘洿澶氬钩鍙扮浉鍏崇殑闂銆?

鑰屽叿浣撲袱鑰呯殑鎬ц兘娴嬭瘯锛屽彲浠ョ湅杩欓噷[6]锛岀粨璁烘槸 Flutter锛屽湪 CPU锛孎PS锛屽唴瀛樼ǔ瀹氫笂鍧囦紭浜?ReactNative銆?/p>

Dart 璇█

鍦ㄥ紑濮?Flutter 涔嬪墠锛屾垜浠渶瑕佸厛浜嗚В涓?Dart 璇█鈥︹€?Dart 鏄敱 Google 寮€鍙戯紝鏈€鍒濇槸鎯充綔涓?JavaScript 鏇夸唬璇█锛屼絾鏄け璐ユ矇瀵備箣鍚庯紝浣滀负 Flutter 鐙湁寮€鍙戣瑷€鍙堢剷鍙戜簡绗簩鏄?馃槀銆傚疄闄呬笂鍗充娇鍒颁簡 2.0锛?span class="mq-50">Dart 璇硶[7]鍜?JavaScriptFlutter[8]闈炲父鐨勭浉鍍忋€傚崟绾跨▼锛孍vent Loop鈥︹€?img data-ratio="0.9888059701492538" src="/img?url=https://mmbiz.qpic.cn/mmbiz_png/gEz4yUa4ueSV30picZ75OH9icA4920FUsicKLTZmfFJaCoDgGUgGJMEaHWRZC207xRn8bygteRTIVKH4DffLSuF8w/640?wx_fmt=png" data-type="png" data-w="804" alt="鍐欑粰鍓嶇宸ョ▼甯堢殑 Flutter 鏁欑▼" class="mq-54">褰撶劧浣滀负涓€绡囧啓缁欏墠绔伐绋嬪笀鐨勬暀绋嬶紝鎴戝湪杩欓噷鍙兂鍐欏啓 JavaScript 涓殏鏃舵病鏈夌殑锛孌art 涓洿涓虹渷蹇冿紝涔熸洿鈥滅敎鈥濈殑涓滆タ銆?/p>

  • 涓嶄細椋樼殑 this
  • 寮虹被鍨嬶紝褰撶劧鍓嶇鐜板湪鏈変簡 TypeScript 馃槵
  • 寮哄ぇ鏂逛究鐨勬搷浣滅鍙凤細
    • ?. 鏂逛究瀹夊叏鐨? foo?.bar鍙栧€硷紝濡傛灉 foo 涓? null锛岄偅涔堝彇鍊间负 null
    • ?? condition ? expr1 : expr2 鍙互绠€鍐欎负 expr1 ?? expr2
    • =鍜屽叾浠栫鍙风殑缁勫悎: *=銆? ~/=銆? &=銆? |= 鈥︹€?
    • 绾ц仈鎿嶄綔绗?Cascade notation ..)
// 鎯虫兂杩欐牱鐪佷簡澶氬皯鍙橀噺澹版槑
querySelect('#button')
 ..text ="Confirm"
 ..classes.add('important')
 ..onClick.listen((e) => window.alert('Confirmed'))

鐢氳嚦鍙互閲嶅啓鎿嶄綔绗?/p>

class Vector {
  final int x, y;
  Vector(this.x, this.y);
  Vector operator +(Vector v) => Vector(x + v.x, y + v.y);
  Vector operator -(Vector v) => Vector(x - v.x, y - v.y);
  // Operator == and hashCode not shown. For details, see note below.
  // 路路路
}
void main() {
  final v = Vector(23);
  final w = Vector(22);
  assert(v + w == Vector(45));
  assert(v - w == Vector(01));
}

娉細閲嶅啓==锛屼篃闇€瑕侀噸鍐?Object hashCodegetter

class Person {
  final String firstName, lastName;
  Person(this.firstName, this.lastName);
  // Override hashCode using strategy from Effective Java,
  // Chapter 11.
  @override
  int get hashCode {
    int result = 17;
    result = 37 * result + firstName.hashCode;
    result = 37 * result + lastName.hashCode;
    return result;
  }
  // You should generally implement operator == if you
  // override hashCode.
  @override
  bool operator ==(dynamic other) {
    if (other is! Person) return false;
    Person person = other;
    return (person.firstName == firstName &&
        person.lastName == lastName);
  }
}
void main() {
  var p1 = Person('Bob''Smith');
  var p2 = Person('Bob''Smith');
  var p3 = 'not a person';
  assert(p1.hashCode == p2.hashCode);
  assert(p1 == p2);
  assert(p1 != p3);
}

杩欑偣鍦?diff 瀵硅薄鐨勬椂鍊欏挨鍏舵湁鐢ㄣ€?/p>

lsolate

Dart 杩愯鍦ㄧ嫭绔嬮殧绂荤殑 iSolate 涓氨绫讳技 JavaScript 涓€鏍凤紝鍗曠嚎绋嬩簨浠堕┍鍔紝浣嗘槸 Dart 涔熷紑鏀句簡鍒涘缓鍏朵粬 isolate锛屽厖鍒嗗埄鐢?CPU 鐨勫鍜岃兘鍔涖€?/p>

loadData() async {
   // 閫氳繃spawn鏂板缓涓€涓猧solate锛屽苟缁戝畾闈欐€佹柟娉?/span>
   ReceivePort receivePort =ReceivePort();
   await Isolate.spawn(dataLoader, receivePort.sendPort);
   
   // 鑾峰彇鏂癷solate鐨勭洃鍚琾ort
   SendPort sendPort = await receivePort.first;
   // 璋冪敤sendReceive鑷畾涔夋柟娉?/span>
   List dataList = await sendReceive(sendPort, 'https://hicc.me/posts');
   print('dataList $dataList');
}
// isolate鐨勭粦瀹氭柟娉?/span>
static dataLoader(SendPort sendPort) async{
   // 鍒涘缓鐩戝惉port锛屽苟灏唖endPort浼犵粰澶栫晫鐢ㄦ潵璋冪敤
   ReceivePort receivePort =ReceivePort();
   sendPort.send(receivePort.sendPort);
   
   // 鐩戝惉澶栫晫璋冪敤
   await for (var msg in receivePort) {
     String requestURL =msg[0];
     SendPort callbackPort =msg[1];
   
     Client client = Client();
     Response response = await client.get(requestURL);
     List dataList = json.decode(response.body);
     // 鍥炶皟杩斿洖鍊肩粰璋冪敤鑰?/span>
     callbackPort.send(dataList);
  }    
}
// 鍒涘缓鑷繁鐨勭洃鍚琾ort锛屽苟涓斿悜鏂癷solate鍙戦€佹秷鎭?/span>
Future sendReceive(SendPort sendPort, String url) {
   ReceivePort receivePort =ReceivePort();
   sendPort.send([url, receivePort.sendPort]);
   // 鎺ユ敹鍒拌繑鍥炲€硷紝杩斿洖缁欒皟鐢ㄨ€?/span>
   return receivePort.first;
}

褰撶劧 Flutter 涓皝瑁呬簡compute[9]锛屽彲浠ユ柟渚跨殑浣跨敤锛岃濡?span class="mq-203">鍦ㄥ叾瀹?isolate 涓В鏋愬ぇ鐨?json[10]銆?/p>

Dart UI as Code

鍦ㄨ繖閲屽崟鐙彁鍑烘潵鐨勬剰涔夊湪浜庯紝浠?React 寮€濮嬶紝鍒?Flutter锛屽埌鏈€杩戠殑 Apple SwiftUI锛孉ndroid Jetpack Compose 澹版槑寮忕粍浠跺啓娉曡秺鍙戞祦琛岋紝Web 鍓嶇浣跨敤 JSX 鏉ヨ寮€鍙戣€呮洿鏂逛究鐨勪功鍐欙紝鑰?Flutter锛孲wiftUI 鍒欑洿鎺ヤ粠浼樺寲璇█鏈韩鐫€鎵嬨€?/p>

鍑芥暟绫荤殑鍛藉悕鍙傛暟

void test({@required int age,String name}) {
  print(name);
  print(age);
}
// 瑙e喅鍑芥暟璋冪敤鏃跺€欙紝鍙傛暟涓嶆槑纭殑闂
test(name:"hicc",age: 30)
// 杩欐牱瀵逛簬缁勪欢鐨勪娇鐢ㄥ挨涓烘柟渚?/span>
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
  return Scaffold(
      appBar: AppBar(),
      body: Container(),
      floatingActionButton:FloatingActionButton()
    );
  }
}

澶ф潃鍣細Collection If 鍜?Collection For

// collection If
Widget build(BuildContext context) {
  return Row(
    children: [
      IconButton(icon: Icon(Icons.menu)),
      Expanded(child: title),
      if (!isandroid)
        IconButton(icon: Icon(Icons.search)),
    ],
  );
}
// Collect For
var command = [
  engineDartPath,
  frontendServer,
  for (var root in fileSystemRoots) "--filesystem-root=$root",
  for (var entryPoint in entryPoints)
    if (fileExists("lib/$entryPoint.json")) "lib/$entryPoint",
  mainPath
];

鏇村 Dart 2.3 瀵规鐨勪紭鍖栫湅杩欓噷[11]銆?/p>

Flutter 鎬庝箞鍐?/h2>

鍒拌繖閲岀粓浜庡埌姝i浜嗭紝濡傛灉鐔熸倝 web 鍓嶇锛岀啛鎮?React 鐨勮瘽锛屼綘浼氬涓嬮潰瑕佽鐨勫紓甯哥殑鐔熸倝銆?img data-ratio="0.36220472440944884" src="/img?url=https://mmbiz.qpic.cn/mmbiz_png/gEz4yUa4ueSV30picZ75OH9icA4920FUsicRWFvfSiauXEibdfU3Nias4HGktTiayrVuzMlEd6Po83GutC7qjBtC2VAlg/640?wx_fmt=png" data-type="png" data-w="762" alt="鍐欑粰鍓嶇宸ョ▼甯堢殑 Flutter 鏁欑▼" class="mq-265">Flutter App 鐨勪竴鍒囦粠lib/main.dart鏂囦欢鐨?main 鍑芥暟寮€濮嬶細

import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Welcome to Flutter'),
        ),
        body: Center(
          child: Text('Hello World'),
        ),
      ),
    );
  }
}

Dart 绫?build 鏂规硶杩斿洖鐨勪究鏄?Widget锛屽湪 Flutter 涓竴鍒囬兘鏄?Widget锛屽寘鎷絾涓嶉檺浜?/p>

  • 缁撴瀯鎬у厓绱狅紝menu锛宐utton 绛?
  • 鏍峰紡绫诲厓绱狅紝font锛宑olor 绛?
  • 甯冨眬绫诲厓绱狅紝padding锛宮argin 绛?
  • 瀵艰埅
  • 鎵嬪娍

Widget 鏄?Dart 涓壒娈婄殑绫伙紝閫氳繃瀹炰緥鍖?Dart 涓?span class="mq-291">new 鏄彲閫夌殑[12])鐩镐簰宓屽锛屼綘鐨勮繖涓?App 灏辨槸褰㈠涓嬪浘鐨勪竴棰楃粍浠舵爲(Dart 鍏ュ彛鍑芥暟鐨勬蹇碉紝main.dart -> main())銆?img data-ratio="0.5609492988133765" src="/img?url=https://mmbiz.qpic.cn/mmbiz_png/gEz4yUa4ueSV30picZ75OH9icA4920FUsic9oYORrfTdx6qCmy2PxIqEDofjAJIfhsox1kgrz5TCqYD190ehRxRZQ/640?wx_fmt=png" data-type="png" data-w="1854" alt="鍐欑粰鍓嶇宸ョ▼甯堢殑 Flutter 鏁欑▼" class="mq-294">

Widget 甯冨眬

涓婅杩?Flutter 甯冨眬鎬濊矾鏉ヨ嚜 CSS锛岃€?Flutter 涓竴鍒囩殕 Widget锛屽洜姝ゆ暣浣撳竷灞€涔熷緢绠€鍗曪細

  • 瀹瑰櫒缁勪欢 Container
    • decoration 瑁呴グ灞炴€э紝璁剧疆鑳屾櫙鑹诧紝鑳屾櫙鍥撅紝杈规锛屽渾瑙掞紝闃村奖鍜屾笎鍙樼瓑
    • margin
    • padding
    • alignment
    • width
    • height
  • Padding锛孋enter
  • Row,Column,Flex
  • Wrap, Flow 娴佸紡甯冨眬
  • Stack锛?z 杞村竷灞€
  • 鈥︹€?

鏇村鍙互鐪嬭繖閲?/span>[13]Flutter 涓?Widget 鍙互鍒嗕负涓夌被锛屽舰濡?React 涓€滃睍绀虹粍浠垛€濄€佲€滃鍣ㄧ粍浠垛€濓紝鈥渃ontext鈥濄€?/p>

StatelessWidget

杩欎釜灏辨槸 Flutter 涓殑鈥滃睍绀虹粍浠垛€濓紝鑷韩涓嶄繚瀛樼姸鎬侊紝澶栭儴鍙傛暟鍙樺寲灏遍攢姣侀噸鏂板垱寤恒€侳lutter 寤鸿灏介噺浣跨敤鏃犵姸鎬佺殑缁勪欢銆?/p>

StatefulWidget

鐘舵€佺粍浠跺氨鏄被浼间簬 React 涓殑鈥滃鍣ㄧ粍浠垛€濅簡锛孎lutter 涓姸鎬佺粍浠跺啓娉曚細绋嶅井涓嶄竴鏍枫€?/p>

class Counter extends StatefulWidget {
  // This class is the configuration for the state. It holds the
  // values (in this case nothing) provided by the parent and used by the build
  // method of the State. Fields in a Widget subclass are always marked "final".
  @override
  _CounterState createState() => _CounterState();
}
class _CounterState extends State<Counter{
  int _counter = 0;
  void _increment() {
    setState(() {
      // This call to setState tells the Flutter framework that
      // something has changed in this State, which causes it to rerun
      // the build method below so that the display can reflect the
      // updated values. If you change _counter without calling
      // setState(), then the build method won't be called again,
      // and so nothing would appear to happen.
      _counter++;
    });
  }
  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance
    // as done by the _increment method above.
    // The Flutter framework has been optimized to make rerunning
    // build methods fast, so that you can just rebuild anything that
    // needs updating rather than having to individually change
    // instances of widgets.
    return Row(
      children: <Widget>[
        RaisedButton(
          onPressed: _increment,
          child: Text('Increment'),
        ),
        Text('Count: $_counter'),
      ],
    );
  }
}

鍙互鐪嬪埌 Flutter 涓洿鎺ヤ娇鐢ㄤ簡鍜?React 涓悓鍚嶇殑setState鏂规硶锛屼笉杩囦笉浼氭湁鍙橀噺鍚堝苟鐨勪笢瑗匡紝褰撶劧涔熸湁鐢熷懡鍛ㄦ湡[14]銆?img data-ratio="1.4268537074148298" src="/img?url=https://mmbiz.qpic.cn/mmbiz_png/gEz4yUa4ueSV30picZ75OH9icA4920FUsicKoLkLIX38vOcI5FWfOI3nOBfxJLMqP7KfuYHoRnJFWibLeMvRH6fP6A/640?wx_fmt=png" data-type="png" data-w="499" alt="鍐欑粰鍓嶇宸ョ▼甯堢殑 Flutter 鏁欑▼" class="mq-366">鍙互鐪嬪埌涓€涓湁鐘舵€佺殑缁勪欢闇€瑕佷袱涓?Class锛岃繖鏍峰啓鐨勫師鍥犲湪浜庯紝Flutter 涓?Widget 閮芥槸 immmutable 鐨勶紝鐘舵€佺粍浠剁殑鐘舵€佷繚瀛樺湪 State 涓紝缁勪欢浠嶇劧姣忔閲嶆柊鍒涘缓锛學idget 鍦ㄨ繖閲屽彧鏄竴绉嶅缁勪欢鐨勬弿杩帮紝Flutter 浼?diff 杞崲鎴?Element锛岀劧鍚庤浆鎹㈡垚 RenderObject 鎵嶆覆鏌撱€?img data-ratio="0.5806451612903226" src="/img?url=https://mmbiz.qpic.cn/mmbiz_png/gEz4yUa4ueSV30picZ75OH9icA4920FUsicU4gPx6XpFbvzf5CUMPaGjweKYdTOR76N6RylMicxhGRUiaI7D4HELTfg/640?wx_fmt=png" data-type="png" data-w="2108" alt="鍐欑粰鍓嶇宸ョ▼甯堢殑 Flutter 鏁欑▼" class="mq-367">Flutter Widget 鏇村鐨勬覆鏌撴祦绋嬪彲浠ョ湅杩欓噷[15]銆傚疄闄呬笂 Widget 鍙槸浣滀负缁勪欢缁撴瀯涓€绉嶆弿杩帮紝杩樺彲浠ュ甫鏉ョ殑濂藉鏄紝浣犲彲浠ユ洿鏂逛究鐨勫仛涓€浜?span class="mq-370">涓婚鎬х殑缁勪欢[16], Flutter 瀹樻柟鎻愪緵鐨?span class="mq-372">Material Components widgets[17]鍜?span class="mq-374">Cupertino (ios-style) widgets[18]璐ㄩ噺灏辩浉褰撻珮锛屽啀閰嶅悎 Flutter 浜氱绾х殑Hot Reload[19]锛屽紑鍙戜綋楠屽彲浠ヨ鎸轰笉閿欑殑銆?/p>


State Management

setState()鍙互寰堟柟渚跨殑绠$悊缁勪欢鍐呯殑鏁版嵁锛屼絾鏄?Flutter 涓姸鎬佸悓鏍锋槸浠庝笂寰€涓嬫祦杞殑锛屽洜姝や篃浼氶亣鍒板拰 React 涓悓鏍风殑闂锛屽鏋滅粍浠舵爲澶繁锛岄€愬眰鐘舵€佸垱寤哄氨鏄惧緱寰堥夯鐑︿簡锛屾洿涓嶈璇翠唬鐮佺殑鏄撹鍜屾槗缁存姢鎬т簡銆?/p>

InheritedWidget

鍚屾牱 Flutter 涔熸湁涓?code class="mq-387">context涓€鏍风殑涓滆タ锛岄偅灏辨槸InheritedWidget锛屼娇鐢ㄨ捣鏉ヤ篃寰堢畝鍗曘€?/p>

class GlobalData extends InheritedWidget {
  final int count;
  GlobalData({Key key, this.count,Widget child}):super(key:key,child:child);
  @override
  bool updateShouldNotify(GlobalData oldWidget) {
    return oldWidget.count != count;
  }
  static GlobalData of(BuildContext context) => context.inheritFromWidgetOfExactType(GlobalData);
}
class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}
class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage{
  int _counter = 0;
  void _incrementCounter() {
      _counter++;
    });
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: GlobalData(
        count: _counter,
        child: 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,
              ),
              Body(),
              Body2()
            ],
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}
class Body extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    GlobalData globalData = GlobalData.of(context);
    return Text(globalData.count.toString());
  }
}
class Body2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    GlobalData globalData = GlobalData.of(context);
    return Text(globalData.count.toString());
  }

鍏蜂綋瀹炵幇鍘熺悊鍙互鍙傝€?span class="mq-457">杩欓噷[20]锛屼笉杩?Google 灏佽浜嗕竴涓洿涓轰笂灞傜殑搴?span class="mq-459">provider[21]锛屽叿浣撲娇鐢ㄥ彲浠ョ湅杩欓噷[22]銆?/p>

BlOC

BlOC[23]鏄?Flutter team 鎻愬嚭寤鸿鐨勫彟涓€绉嶆洿楂樼骇鐨勬暟鎹粍缁囨柟寮忥紝涔熸槸鎴戞渶涓剰鐨勬柟寮忋€傜畝鍗曟潵璇达細Bloc = InheritedWidget + RxDart(Stream)Dart 璇█涓唴缃簡 Steam锛孲tream ~= Observable锛岄厤鍚?span class="mq-470">RxDart[24], 鐒跺悗鍔犱笂StreamBuilder浼氭槸涓€绉嶅紓甯稿己澶у拰鑷敱鐨勬ā寮忋€?/p>

class GlobalData extends InheritedWidget {
  final int count;
  final Stream<String> timeInterval$ = new Stream.periodic(Duration(seconds: 10)).map((time) => new DateTime.now().toString());
  GlobalData({Key key, this.count,Widget child}):super(key:key,child:child);
  @override
  bool updateShouldNotify(GlobalData oldWidget) {
    return oldWidget.count != count;
  }
  static GlobalData of(BuildContext context) => context.inheritFromWidgetOfExactType(GlobalData);
}
class TimerView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    GlobalData globalData = GlobalData.of(context);
    return StreamBuilder(
        stream: globalData.timeInterval$,
        builder: (context, snapshot) {
          return Text(snapshot?.data ?? '');
        }
    );
  }
}

褰撶劧 Bloc 鐨勯棶棰樺湪浜?/p>

  • 瀛︿範鎴愭湰鐣ラ珮锛孯x 鐨勬蹇佃鍚冮€忥紝涓嶇劧浣犱細鎶撶媯
  • 鑷敱甯︽潵鐨勯棶棰樻槸锛屽彲鑳戒唬鐮佷笉濡?Redux 绫荤殑瑙勬暣銆?

椤轰究锛屼粖骞?Apple 涔熸嫢鎶变簡鍝嶅簲寮忥紝Combine[25](Rx like) + SwiftUI 涔熷熀鏈瓑浜?Bloc 浜嗐€傛墍浠ワ紝Rx 杩樻槸瑕佽刀绱у璧锋潵 馃槵 闄ゅ幓 Bloc锛孎lutter 涓繕鏄彲浠ヤ娇鐢ㄥ叾浠栫殑鏂规锛岃濡傦細

  • Flutter Redux [26]
  • 闃块噷闂查奔鐨? Fish Redux [27]锛? 鎹鎬ц兘寰堝ソ銆?
  • Mobx [28]
  • 鈥︹€?

灞曞紑鏉ヨ鐜板湪鐨勫墠绔紑鍙戜娇鐢ㄥ己澶х殑妗嗘灦椤甸潰缁勮宸茬粡涓嶆槸闅剧偣浜嗐€傚紑鍙戠殑闅剧偣鍦ㄤ簬濡備綍缁勫悎瀵屼氦浜掓墍闇€鐨勬暟鎹紝涔熷氨鏄笂闈㈠浘涓殑state閮ㄥ垎銆傛洿鍏蜂綋鏉ヨ锛屾槸鎬庝箞浼橀泤锛岄珮鏁堬紝鏄撶淮鎶ゅ湴澶勭悊鐭殏鏁版嵁(ephemeral state)setState()鍜岄渶瑕佸叡浜殑 App State 鐨勯棶棰橈紝杩欐槸涓伐绋嬫€х殑闂锛屼絾寰€寰€涔熸槸鏃ュ父寮€鍙戞渶闅剧殑浜嬫儏浜嗭紝寮曠敤 Redux 浣滆€?Dan 鐨勪竴鍙ワ細

鈥淭he rule of thumb is:Do whatever is less awkward[29].鈥?/p>

鍒拌繖閲岋紝涓昏鐨勯儴鍒嗗凡缁忚瀹屼簡锛屾湁杩欎簺宸茬粡鍙互寮€鍙戝嚭涓€涓笉閿欑殑 App 浜嗐€傚墿涓嬬殑灏卞綋鎴愪竴涓?bonus 鍚с€?/p>


娴嬭瘯

Flutter debugger锛屾祴璇曢兘鏄嚭鍦鸿嚜甯︼紝鐢ㄨ捣鏉ヤ篃涓嶉毦銆?/p>

// 娴嬭瘯鍦?test/鐩綍涓嬮潰
void main() {
  testWidgets('Counter increments smoke test', (WidgetTester tester) async {
    // Build our app and trigger a frame.
    await tester.pumpWidget(MyApp());
    // Verify that our counter starts at 0.
    expect(find.text('0'), findsOneWidget);
    expect(find.text('1'), findsNothing);
    // Tap the '+' icon and trigger a frame.
    await tester.tap(find.byIcon(Icons.add));
    await tester.pump();
    // Verify that our counter has incremented.
    expect(find.text('0'), findsNothing);
    expect(find.text('1'), findsOneWidget);
  });
}

鍖呯鐞嗭紝璧勬簮绠$悊

绫讳技涓?JavaScript 鐨?npm锛孎lutter锛屼篃灏辨槸 Dart 涔熸湁鑷繁鐨?span class="mq-557">鍖呬粨搴?/span>[30]銆備笉杩囬」鐩寘鐨勪緷璧栦娇鐢?yaml 鏂囦欢鏉ユ弿杩?

name: app
description: A new Flutter project.
version: 1.0.0+1
environment:
  sdk: ">=2.1.0 <3.0.0"
dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^0.1.2

鐢熷懡鍛ㄦ湡

绉诲姩搴旂敤鎬诲綊闇€瑕佸簲鐢ㄧ骇鍒殑鐢熷懡鍛ㄦ湡锛宖lutter 涓娇鐢ㄧ敓鍛藉懆鏈熼挬瀛愶紝涔熼潪甯哥殑绠€鍗曪細

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyAppwith WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
  }
  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }
  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    switch (state) {
      case AppLifecycleState.inactive:
        print('AppLifecycleState.inactive');
        break;
      case AppLifecycleState.paused:
        print('AppLifecycleState.paused');
        break;
      case AppLifecycleState.resumed:
        print('AppLifecycleState.resumed');
        break;
      case AppLifecycleState.suspending:
        print('AppLifecycleState.suspending');
        break;
    }
    super.didChangeAppLifecycleState(state);
  }
  @override
  Widget build(BuildContext context) {
      return Container();
  }
}

浣跨敤鍘熺敓鑳藉姏

鍜?ReactNative 绫讳技锛孎lutter 涔熸槸浣跨敤绫讳技浜嬩欢鐨勬満鍒舵潵浣跨敤骞冲彴鐩稿叧鑳藉姏銆?img data-ratio="1.1155172413793104" src="/img?url=https://mmbiz.qpic.cn/mmbiz_png/gEz4yUa4ueSV30picZ75OH9icA4920FUsic6yibAGrTMlz0GpnTDQicZjy233bkghO1TY6HC1c70fyk0iaQymEaN0ic2w/640?wx_fmt=png" data-type="png" data-w="580" alt="鍐欑粰鍓嶇宸ョ▼甯堢殑 Flutter 鏁欑▼" class="mq-623">

Flutter Web, Flutter Desktop

杩欎簺杩樺湪寮€鍙戝綋涓紝閴翠簬瀵?Dart 鍠滄锛屼互鍙婂 Flutter 鎬ц兘鐨勪箰瑙傦紝杩欎簺鍊掓槸寰堝€煎緱鏈熷緟銆?img data-ratio="0.40897097625329815" src="/img?url=https://mmbiz.qpic.cn/mmbiz_png/gEz4yUa4ueSV30picZ75OH9icA4920FUsicLjKxMfdO141Uib7SGVHBJhNOcibcmxBGBLSHG4nn4YBsdCl0A90cwngw/640?wx_fmt=png" data-type="png" data-w="1137" alt="鍐欑粰鍓嶇宸ョ▼甯堢殑 Flutter 鏁欑▼" class="mq-627">杩樿寰楀钩鍙板彧鏄粰 Flutter 鎻愪緵涓€涓敾甯冧箞锛孎lutter Desktop 鏈潵鏇存槸鍙互澶ф湁鍙负 馃槃锛岀浉鍏冲彲浠ョ湅杩欓噷[31]銆傛渶鍚庢瘡绉嶆柟妗堬紝姣忕鎶€鏈兘鏈?span class="mq-630">浼樼己鐐?/span>[32]锛岀敋鑷虫妧鏈殑鏋舵瀯鍐冲畾浜嗭紝鏈変簺缂洪櫡鍙兘姘歌繙閮芥病娉曟敼杩涳紝鎵€浠?馃


鏈€鍚庣殑鏈€鍚庯紝寮虹儓鎺ㄨ崘闂查奔鍥㈤槦鐨?span class="mq-634">Flutter Blog[33]馃憤锛屽父甯告嫓璇伙紝鏀剁泭鑹

鍙傝€冭祫鏂?/span>

[1]

Flutter: https://flutter.dev/

[2]

mobile: https://flutter.dev/docs

[3]

web: https://flutter.dev/web

[4]

desktop: https://flutter.dev/desktop

[5]

Flutter: https://flutter.dev/

[6]

杩欓噷: https://www.yuque.com/xytech/flutter/gs3pnk

[7]

Dart 璇硶: https://dart.dev/guides/language/language-tour

[8]

Flutter: https://flutter.dev/

[9]

compute: https://api.flutter.dev/flutter/foundation/compute.html

[10]

鍦ㄥ叾瀹?isolate 涓В鏋愬ぇ鐨?json: https://flutter.dev/docs/cookbook/networking/background-parsing

[11]

杩欓噷: https://medium.com/dartlang/making-dart-a-better-language-for-ui-f1ccaf9f546c

[12]

new 鏄彲閫夌殑: https://dart.dev/guides/language/language-tour#using-constructors

[13]

鏇村鍙互鐪嬭繖閲? https://www.yuque.com/xytech/flutter/hc0xq7

[14]

鐢熷懡鍛ㄦ湡: https://segmentfault.com/a/1190000015211309

[15]

杩欓噷: https://www.yuque.com/xytech/flutter/tge705

[16]

涓婚鎬х殑缁勪欢: https://flutter.dev/docs/development/ui/widgets

[17]

Material Components widgets: https://flutter.dev/docs/development/ui/widgets/material

[18]

Cupertino (iOS-style) widgets: https://flutter.dev/docs/development/ui/widgets/cupertino

[19]

Hot Reload: https://flutter.dev/docs/development/tools/hot-reload

[20]

杩欓噷: https://loveky.github.io/2018/07/18/how-flutter-inheritedwidget-works/

[21]

provider: https://pub.dev/packages/provider

[22]

杩欓噷: https://flutter.dev/docs/development/data-and-backend/state-mgmt/simple

[23]

BlOC: https://medium.com/flutterpub/architecting-your-flutter-project-bd04e144a8f1

[24]

RxDart: https://pub.dev/packages/rxdart

[25]

Combine: https://developer.apple.com/documentation/combine

[26]

Flutter Redux: https://pub.dev/packages/flutter_redux

[27]

Fish Redux: https://github.com/alibaba/fish-redux

[28]

Mobx: https://mobx.pub/

[29]

Do whatever is less awkward: https://github.com/reduxjs/redux/issues/1287#issuecomment-175351978

[30]

鍖呬粨搴? https://pub.dev/

[31]

杩欓噷: https://github.com/flutter/flutter/wiki/Desktop-shells

[32]

浼樼己鐐? https://medium.com/asos-techblog/flutter-vs-react-native-for-ios-android-app-development-c41b4e038db9

[33]

Flutter Blog: https://www.yuque.com/xytech/flutter




























鍐欑粰鍓嶇宸ョ▼甯堢殑 Flutter 鏁欑▼

        
          
          
        

鈼?nbsp;

鈼?nbsp;

鈼?nbsp;


路END路

鍥鹃泙绀惧尯

姹囪仛绮惧僵鐨勫厤璐瑰疄鎴樻暀绋?/span>



鍏虫敞鍏紬鍙峰洖澶?z 鎷夊涔犱氦娴佺兢


鍠滄鏈枃锛岀偣涓€?span>鍦ㄧ湅鈥濆憡璇夋垜

以上是关于鍐欑粰鍓嶇宸ョ▼甯堢殑 Flutter 鏁欑▼的主要内容,如果未能解决你的问题,请参考以下文章

杩欎唤涔﹀崟锛屾兂瑕佹檵绾ч珮绾ava宸ョ▼甯堢殑鏈嬪弸鍊煎緱涓€鐪嬶紒

杩欎簺鐑棬GitHub浠g爜搴擄紝姣忎釜鍓嶇寮€鍙戣€呴兘搴旇鏀惰棌

鏈哄櫒瀛︿範瀹炴垬锛氭敮鎸佸悜閲忔満(涓?

PHP鏁欑▼锛歅HP寮€鍙戝揩閫熷叆闂╛v20200418