<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          5分鐘學(xué)會(huì)Flutter開發(fā)

          共 13637字,需瀏覽 28分鐘

           ·

          2021-09-02 19:38

          點(diǎn)擊“開發(fā)者技術(shù)前線”,選擇“星標(biāo)??”

          讓一部分開發(fā)者看到未來


          導(dǎo)讀:Flutter是Google開源的構(gòu)建用戶界面(UI)工具包,幫助開發(fā)者通過一套代碼庫高效構(gòu)建多平臺(tái)應(yīng)用,支持移動(dòng)、Web、桌面和嵌入式平臺(tái)。Flutter使用Dart為開發(fā)語言,利用Skia繪圖引擎,直接通過CPU、GPU進(jìn)行繪制,不需要依賴任何原生的控件,相比React Native(依賴中間者JSCore引擎)性能更高。
          全文3560字,預(yù)計(jì)閱讀時(shí)間 14分鐘。

          目前Flutter混合棧技術(shù)成熟,基礎(chǔ)建設(shè)完善,百度貼吧、網(wǎng)盤、地圖、閱讀、輸入法等均已接入Flutter,一套代碼雙端運(yùn)行,約節(jié)省50%人力。

          一、環(huán)境配置:
          1.1 下載Flutter SDK

          git clone https://github.com/flutter/flutter.git

          1.2 配置環(huán)境變量
          編輯~/.bash_profile,將環(huán)境變量添加至末尾。(如終端安裝了zsh插件,則添加環(huán)境變量至 ~/.zshrc)

          # FLUTTER_HOME為下載的Flutter文件夾路徑export FLUTTER_HOME=/Users/.../flutterexport PATH=$PATH:$FLUTTER_HOME/binexport PATH=$PATH:$FLUTTER_HOME/bin/cache/dart-sdk/bin

          1.3 刷新環(huán)境變量
          source ~/.bash_profilesource ~/.zshrc(如安裝zsh插件)

          1.4 開發(fā)工具
          1. Xcode + Android Studio(推薦)
          2. Visual Studio Code
          以 Xcode + Android Studio為例,配置Android Studio插件:
          1.4.1 安裝 Flutter,Dart插件
          Android Studio - Preferences - Plugins - Marketplace

          1.4.2 安裝最新 Android SDK Command
          Android Studio - Preferences - SystemSettings - Android SDK - SDK Tools - 勾選Android SDK Command-line Tools

          1.4.3 運(yùn)行 flutter doctor

          *報(bào)錯(cuò):Unable to find bundled Java version on Flutter
          cd /Applications/Android\ Studio.app/Contents/jreln -s ../jre jdkln -s "/Library/Internet Plug-Ins/JavaAppletPlugin.plugin" jdkflutter doctor

          二、工程創(chuàng)建
          2.1 創(chuàng)建Flutter項(xiàng)目
          flutter create xxx

          2.2 創(chuàng)建Flutter模塊(用于原生集成Flutter)
          create --template module xxx

          2.3 工程結(jié)構(gòu)
          bd_flutter .dart_tool.............記錄依賴庫信息 .idea..................當(dāng)前項(xiàng)目配置 android................Android工程目錄 iOS....................iOS工程目錄 lib....................Flutter代碼目錄 test...................單元測試目錄 web....................Web工程目錄 pubspec.yaml...........Pub第三方依賴配置文件,類似Cocoapods、Gradle

          三、編程范式

          在 Flutter 中界面布局使用 Dart 語言聲明式編程范式,更易于開發(fā)與閱讀。

          3.1 命令式編程
          命令“機(jī)器”如何去做事情(注重 how) 。

          3.2 聲明式編程
          告訴“機(jī)器”你想要的是什么(注重 what) 。
          2009年開始Vue、React、SwiftUI、Flutter以聲明式編程為主,正逐步成為大前端的一種編程趨勢。

          3.3 我們舉一個(gè)栗子,來幫我我們理解這兩者的區(qū)別
          3.3.1 點(diǎn)擊按鈕修改文本(OC、Java版本)

          3.3.2 點(diǎn)擊按鈕修改文本(Flutter、SwiftUI版本)

          在聲明式編程中,首先代碼是結(jié)構(gòu)化的;其次,開發(fā)者無需關(guān)注Label/Text控件更新,引擎會(huì)自動(dòng)根據(jù)num值的改變修改引用控件的值。


          四、基礎(chǔ)架構(gòu)


          Flutter被設(shè)計(jì)為一個(gè)可擴(kuò)展的分層系統(tǒng)。它可以被看作是各個(gè)獨(dú)立的組件的系列合集,上層組件各自依賴下層組件。組件無法越權(quán)訪問更底層的內(nèi)容,并且框架層中的各個(gè)部分都是可選且可替代的。從下到上分為三層,依次為:Embedder、Engine、Framework。

          4.1 Embedder
          Embedder是操作系統(tǒng)適配層,實(shí)現(xiàn)了渲染 Surface 設(shè)置,線程設(shè)置等。

          4.2 Engine
          Engine層是 Flutter 的核心,它主要使用 C++ 編寫,并提供了 Flutter 應(yīng)用所需的原語。當(dāng)需要繪制新一幀的內(nèi)容時(shí),引擎將負(fù)責(zé)對需要合成的場景進(jìn)行柵格化。它提供了 Flutter 核心 API 的底層實(shí)現(xiàn),包括圖形(通過 Skia 鏈接:https://skia.org/)、文本布局、文件及網(wǎng)絡(luò) IO、輔助功能支持、插件架構(gòu)和 Dart 運(yùn)行環(huán)境及編譯環(huán)境的工具鏈。

          4.3 Framework
          Framework 層是一個(gè)用 Dart 實(shí)現(xiàn)的 UI SDK,包含了動(dòng)畫、圖形繪制和手勢識(shí)別等功能。開發(fā)者可以通過 Flutter 框架層與 Flutter 交互,該框架提供了以 Dart 語言編寫的現(xiàn)代響應(yīng)式框架。它包括由一系列層組成的一組豐富的平臺(tái),布局和基礎(chǔ)庫。從下層到上層,依次有:

          1、基礎(chǔ)的Foundation 類及一些基層之上的構(gòu)建塊服務(wù),如 animation、 painting 和 gestures,它們可以提供上層常用的抽象。
          2、渲染層用于提供操作布局的抽象。有了渲染層,你可以構(gòu)建一棵可渲染對象的樹。在你動(dòng)態(tài)更新這些對象時(shí),渲染樹也會(huì)自動(dòng)根據(jù)你的變更來更新布局。
          3、widget層是一種組合的抽象。每一個(gè)渲染層中的渲染對象,都在 widgets 層中有一個(gè)對應(yīng)的類。此外,widgets 層讓你可以自由組合你需要復(fù)用的各種類。響應(yīng)式編程模型就在該層級(jí)中被引入。
          4、Material 和 Cupertino 庫提供了全面的 widgets 層的原語組合,這套組合分別實(shí)現(xiàn)了 Material 和 iOS 設(shè)計(jì)規(guī)范。

          五、視圖渲染
          5.1 Widget
          Flutter中沒有Controller、Activity概念,只有一種控件Widget(相當(dāng)于View),一切皆 Widget。
          Widget 是 Flutter 功能的抽象描述,是視圖的配置信息,同樣也是數(shù)據(jù)的映射,是 Flutter 開發(fā)框架中最基本的概念。
          兩個(gè)比較重要的Widget:StatelessWidget和StatefulWidget。

          5.2 渲染過程
          5.2.1 Flutter引擎不會(huì)直接渲染widget樹,因?yàn)閣idget是特別不穩(wěn)定的,會(huì)頻繁的調(diào)用build方法,widget又相互依賴,一旦調(diào)用build,后面的widget都會(huì)重新創(chuàng)建,直接去解析widget的話會(huì)非常消耗性能,布局需要重新計(jì)算。由此引出了Element,RenderObject的概念,F(xiàn)lutter引擎解析的是RenderObject樹,并非widget。
          5.2.2 Widget會(huì)轉(zhuǎn)化成RenderObject,但并不是所有的widget都會(huì)轉(zhuǎn)成RenderObject。

          非RenderObject轉(zhuǎn)化:
          //Text -> StatelessWidget -> Widget
          class Text extends StatelessWidget {}abstract class StatelessWidget extends Widget {StatelessElement createElement() => StatelessElement(this);}abstract class Widget extends DiagnosticableTree {Element createElement(); // 創(chuàng)建element抽象方法}

          RenderObject轉(zhuǎn)化:
          //Column -> Flex -> MultiChildRenderObjectWidget - > RenderObjectWidget -> Widgetclass Column extends Flex {}class Flex extends MultiChildRenderObjectWidget {// ?法實(shí)現(xiàn)RenderFlex createRenderObject(BuildContext context) {//返回RenderFlexreturn RenderFlex -> RenderBox -> RenderObject} }abstract class MultiChildRenderObjectWidget extends RenderObjectWidget {}abstract class RenderObjectWidget extends Widget {RenderObjectElement createElement();RenderObject createRenderObject(BuildContext context); // 抽象?法-創(chuàng)建RenderObjectvoid updateRenderObject(BuildContext context, covariant RenderObject renderObject) {}void didUnmountRenderObject(covariant RenderObject renderObject) { }}abstract class Widget extends DiagnosticableTree {Element createElement(); // 抽象?法-創(chuàng)建element}class RenderFlex extends RenderBox with ContainerRenderObjectMixin<RenderBox,FlexParentData>, RenderBoxContainerDefaultsMixin<RenderBox,FlexParentData>, DebugOverflowIndicatorMixin {}abstract class RenderBox extends RenderObject {}

          六、混合開發(fā)
          6.1 Flutter調(diào)用原生方法

          1.Platform channels
          2.Pigeon
          3.https://pub.dev/ 中搜索第三方開源包
          以Platform channels為例:Flutter調(diào)用原生獲取UDID

          /*Flutter代碼*/static const platform = const MethodChannel("leo.com/getudid");void getUDID() async {final result = await platform.invokeMethod("nativeGetUDID"); // 要調(diào)?的?法// final result = await platform.invokeMethod("nativeGetUDID",["flutter參數(shù)"]);setState(() {_udid = result; });}
          /*iOS代碼*/// 1.獲取FlutterViewControllerlet controller: FlutterViewController = window.rootViewController as!FlutterViewController;// 2.創(chuàng)建FlutterMethodChannel,跟controller?進(jìn)制消息通信let channel = FlutterMethodChannel(name: "leo.com/getudid", binaryMessenger:controller.binaryMessenger);// 3.監(jiān)聽channel調(diào)??法,當(dāng)flutter調(diào)?nativeGetUDID的時(shí)候調(diào)?channel.setMethodCallHandler { (call: FlutterMethodCall, result: @escapingFlutterResult) in// 1.判斷當(dāng)前是否是nativeGetUDIDguard call.method == "nativeGetUDID" else {result(FlutterMethodNotImplemented); // 報(bào)?個(gè)沒有?法的錯(cuò)誤return; }call.arguments; //傳遞過來的參數(shù)// 2.獲取UDIDlet udid = "xxxx-xxxx-xxxx-xxxx"result(udid) //回調(diào)值}
          /*Android代碼*/private val CHANNEL = "leo.com/getudid"override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {GeneratedPluginRegistrant.registerWith(flutterEngine);// 1.創(chuàng)建MethodChannel對象val methodChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger,CHANNEL)// 2.添加調(diào)??法的回調(diào)methodChannel.setMethodCallHandler {// Note: this method is invoked on the main thread.call, result ->// 2.1.如果調(diào)?的?法是nativeGetUDID,那么正常執(zhí)?if (call.method == "nativeGetUDID") {// 2.1.1.調(diào)?另外?個(gè)?定義?法回去電量信息val udid = "xxxx-xxxx-xxxx-xxxx";result.success(udid) } else {//?法找不到,回調(diào)notImplementedresult.notImplemented() } }}

          6.2 原?集成Flutter創(chuàng)建Flutter模塊
          create --template module native_add_flutter

          6.2.1 iOS集成Flutter
          // CocoaPods集成flutter_application_path = '../native_add_flutter'load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb’)
          // 初始化Flutter引擎 , 為引擎起名為leolet flutterEngine:FlutterEngine = FlutterEngine(name: "leo");// 啟動(dòng)flutter引擎,默認(rèn)函數(shù)??為mainflutterEngine.run();let flutterVC = FlutterViewController(engine: engine, nibName: nil, bundle: nil);flutterVC.modalPresentationStyle = .fullScreen;self.present(flutterVC, animated: true, completion: nil);

          6.2.2 Android集成Flutter
          // 在gradle進(jìn)?配置// 創(chuàng)建Android項(xiàng)?、添加相關(guān)的依賴// 1、修改Android項(xiàng)?settings.gradlesetBinding(new Binding([gradle: this])) // newevaluate(new File( // newsettingsDir.parentFile, // new'native_add_flutter/.android/include_flutter.groovy' // new))include ':native_add_flutter'project(':native_add_flutter').projectDir = new File('../native_add_flutter')// 2、配置Android項(xiàng)?的build.gradledependencies { ...implementation project(':flutter') //增加flutter依賴}// 3、AndroidManifest.xml配置<activity android:name="io.flutter.embedding.android.FlutterActivity"android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"android:hardwareAccelerated="true"android:windowSoftInputMode="adjustResize"/>
          import io.flutter.embedding.android.FlutterActivity;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);startActivity(FlutterActivity.createDefaultIntent(this) ); }}

          七、案例講解 - 計(jì)數(shù)器
          flutter create flutterdemo
          main.dart
          // 導(dǎo)?類import 'package:flutter/material.dart';//??函數(shù),程序加載時(shí)調(diào)?void main() {runApp(MyApp()); //調(diào)?runApp?法,并初始化MyApp}class MyApp extends StatelessWidget {// This widget is the root of your application.@overrideWidget build(BuildContext context) { //初始化會(huì)調(diào)?build?法return MaterialApp( //Material為Google的?種UI?格,MaterialApp可為項(xiàng)?配置App標(biāo)題、主題title: 'Flutter Demo',theme: ThemeData(// This is the theme of your application.//// Try running your application with "flutter run". You'll see the// application has a blue toolbar. Then, without quitting the app, try// changing the primarySwatch below to Colors.green and then invoke// "hot reload" (press "r" in the console where you ran "flutter run",// or simply save your changes to "hot reload" in a Flutter IDE).// Notice that the counter didn't reset back to zero; the application// is not restarted.primarySwatch: Colors.blue, ),home: MyHomePage(title: 'Flutter Demo Home Page'), //設(shè)置主?為MyHomePage ); }}//由于點(diǎn)擊需要更改Text顯示,所以此處繼承StatefulWidgetclass MyHomePage extends StatefulWidget {MyHomePage({Key? key, required this.title}) : super(key: key);// This widget is the home page of your application. It is stateful, meaning// that it has a State object (defined below) that contains fields that affect// how it looks.// This class is the configuration for the state. It holds the values (in this// case the title) provided by the parent (in this case the App widget) and// used by the build method of the State. Fields in a Widget subclass are// always marked "final".final String title;@override_MyHomePageState createState() => _MyHomePageState();}class _MyHomePageState extends State<MyHomePage> {int _counter = 0;//下的按鈕的點(diǎn)擊事件void _incrementCounter() {// setState會(huì)標(biāo)記需要刷新UIsetState(() {// 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 we changed// _counter without calling setState(), then the build method would not be// called again, and so nothing would appear to happen._counter++; //點(diǎn)擊按鈕時(shí)候,counter+1, 并?動(dòng)更新UI顯示 }); }@overrideWidget build(BuildContext context) {// This method is rerun every time setState is called, for instance as done// by the _incrementCounter 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 Scaffold(appBar: AppBar( //配置導(dǎo)航// 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 is a layout widget. It takes a single child and positions it// in the middle of the parent.child: Column( //?種豎向布局?式,相當(dāng)于listview// Column is also a layout widget. It takes a list of children and// arranges them vertically. By default, it sizes itself to fit its// children horizontally, and tries to be as tall as its parent.//// Invoke "debug painting" (press "p" in the console, choose the// "Toggle Debug Paint" action from the Flutter Inspector in Android// Studio, or the "Toggle Debug Paint" command in Visual Studio Code)// to see the wireframe for each widget.//// Column has various properties to control how it sizes itself and// how it positions its children. Here we use mainAxisAlignment to// center the children vertically; the main axis here is the vertical// axis because Columns are vertical (the cross axis would be// horizontal).mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[ //返回多個(gè)widget數(shù)組,Text('You have pushed the button this many times:', ),Text( '$_counter',//顯示_counter的值style: Theme.of(context).textTheme.headline4,//顯示樣式,使?主題的headline4顯示 ), ], ), ),floatingActionButton: FloatingActionButton( //?個(gè)可點(diǎn)擊的按鈕,固定在右下?onPressed: _incrementCounter, //點(diǎn)擊事件tooltip: 'Increment',child: Icon(Icons.add), //按鈕顯示為內(nèi)部?帶的add圖? ), // This trailing comma makes auto-formatting nicer for build methods.  ); }}

          八、附:近期重要更新

          1.2版本 2019/02/26
          支持java1.8
          增加了JavaScript與Dart的通信通道
          增加了對Android App Bundles的支持
          通過減少調(diào)用構(gòu)造函數(shù)和靜態(tài)方法,提升AOT(預(yù)編譯)10%-20%的性能

          1.5版本 2019/05/07
          添加了集成測試
          提高熱重載性能
          決定刪除動(dòng)態(tài)更新計(jì)劃
          添加對Linux和Windows的Flutter運(yùn)行支持

          1.7版本 2019/07/09
          優(yōu)化Flutter tools支持
          支持32位和64位Android bundles
          開始支持web端和實(shí)驗(yàn)性支持桌面端

          1.9版本 2019/09/10
          完善Web平臺(tái)支持
          桌面平臺(tái)實(shí)驗(yàn)性支持
          新增24種語言環(huán)境支持
          支持macOS Catalina和iOS 13
          Android增加對構(gòu)建AAR的支持

          1.12版本 2019/12/11
          支持Android 10
          支持iOS13暗黑模式
          可以將Flutter模塊集成到Android或iOS應(yīng)用中
          將Web支持從開發(fā)版轉(zhuǎn)變?yōu)閎eta版;將MacOS支持納入開發(fā)版本
          推出新工具DartPad(DartPad 是一個(gè)可以讓你在任何現(xiàn)代化的瀏覽器中體驗(yàn) Dart 編程語言線上工具)

          1.17版本 2020/05/06
          減少18.5%應(yīng)用體積
          提升了20%-37%導(dǎo)航性能
          降低了40% iOS動(dòng)畫CPU/GPU使用率
          增加對谷歌字體的支持:fonts.google.com
          完成對Type Scale部分的重構(gòu),符合 2018 Material 設(shè)計(jì)規(guī)范
          提升了iOS 50%渲染速度(iPhone5s+、iOS10+支持Metal 渲染);不完全支持扔使用OpenGL渲染

          1.20版本 2020/08/05
          增強(qiáng)了UTF-8解碼
          pubspec.yaml插件不再支持舊格式
          在Visual Studio Code中預(yù)覽嵌入式Dart DevTools
          引入新的混編插件-Pigeon,可以在Dart方法中直接調(diào)用Java/Objective-C/Kotlin/Swift方法并傳遞非原始數(shù)據(jù)對象。

          1.22版本 2020/10/01
          增加應(yīng)用體積分析工具
          提供了國際化和本地化工具,并實(shí)現(xiàn)了熱重載支持
          支持Android 11;支持新的屏幕類型 (如挖孔屏和瀑布屏),以及同步Android 11動(dòng)畫效果
          支持iOS 14、Xcode 12新圖標(biāo)以及對新iOS 14 App Clips功能的預(yù)覽支持;默認(rèn)模板版本從8.0升級(jí)到9.0
          可正式使用的 Google Maps 和 WebView 插件,將 Android 和 iOS 系統(tǒng)的原生界面組件托管在 Flutter 應(yīng)用中

          2.0版本 2021/03/03
          Web支持從測試版轉(zhuǎn)變?yōu)榉€(wěn)定版
          除了HTML渲染,增加了CanvasKit渲染,桌面端瀏覽器會(huì)默認(rèn)調(diào)用CanvasKit版本,移動(dòng)端的瀏覽器會(huì)調(diào)用HTML版本。
          混合開發(fā)多flutter實(shí)例(經(jīng)測試iOS平臺(tái)存在內(nèi)存問題)
          桌面平臺(tái)的支持(beta)
          Google Mobile Ads(Beta)
          Dart 2.12 增加了空安全

          2.2版本 2021/05/18
          更好的iOS、Android、Web跨平臺(tái)支持
          Dart 2.13 更新,引入Type aliases
          Flutter Web 提升穩(wěn)定性
          優(yōu)化iOS端渲染動(dòng)畫幀時(shí)間、實(shí)現(xiàn)了增量iOS安裝,縮短更新安裝時(shí)間。
          Android中引入延遲組件,允許Flutter應(yīng)用在運(yùn)行時(shí)下載包含提前編譯的代碼模塊,減少初始安裝大小。

          —  —

          點(diǎn)這里??關(guān)注我,記得標(biāo)星呀~

          前線推出學(xué)習(xí)交流一定要備注:研究/工作方向+地點(diǎn)+學(xué)校/公司+昵稱(如JAVA+上海

          掃碼加小編微信,進(jìn)群和大佬們零距離



          END



          好文點(diǎn)個(gè)在看吧!
          瀏覽 64
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  aaa亚洲天堂 | 中文字幕精品视频 | 77777在线视频 | 91精品国产综合久久久久久 | 亚洲日日日 |