Flutter介紹與基本使用
1、 環境以及工具的準備
1 下載Flutter SDK
https://flutter.dev/docs/get-started/install/macos
並將其bin路徑加入系統路徑中
java
IDE使用
AndroidStudio使用Flutter
Android Studio 安裝插件 Flutter和Dart插件android
GeneratedPluginRegistrant 將Android的Activity註冊給Flutter
FlutterActivity/FlutterAppDelegate,是Android的Plugin管理器,它記錄了全部的Plugin,並將Plugin綁定到FlutterView/FlutterViewController
ios
Flutter inspector
Flutter Outline
Flutter Performance
web
XCodemacos
VS Code運行Dart
安裝Dart SDK緩存
brew tap dart-lang/dart brew install dart dart --version
VS Code安裝插件
Dart 和 Code Runner插件
併發
3app
2、Flutter介紹
移動端的UI框架框架
1 能夠與原生的Android 和 IOS混合開發
上層FrameWork 使用Dart語言實現 有Material Design(Android)和Cupertino(IOS)風格的Widgets
函數
中間層使用C++編寫的 Skia庫(二維圖形庫)
不是經過使用原生控件,而是本身渲染 佈局是樹結構形式
Skia in Flutter
Flutter用了skia做爲自繪製的渲染庫,所以能實現很好的跨平臺能力,以及有較高的性能。底層仍是使用了OpenGL經過GPU實現硬件渲染
而WebView的軟件渲染方式也是用到了skia庫,只是多了一層chromium(低版本是webkit)引擎進行渲染
Dart部分主要包括:Dart Runtime,Garbage Collection(GC),若是是Debug模式的話,還包括 JIT(Just In Time) 支持。
Release和Profile模式下,是**AOT(Ahead Of Time)**編譯成了原生的arm代碼
Text部分用來進行文本渲染
底層的platform爲IOS 和 Android平臺
經過Platform Channel 與 native的服務進行通訊
JS Bridge
2 Webview跨平臺能力最強,可是性能最差 經過JS Bridge操做原生服務
跨平臺能力與RN Weex至關 可是性能要優於他們 由於不涉及JS Bridge 控件也是本身渲染的
熱重載(Hot Reload),利用Android Studio直接一個ctrl+\就能夠保存並熱重載
優勢:
1 性能高 C++, AOT,skia渲染
目前的缺點
1 安裝包過大
2 無webview 要使用插件
3 不支持熱更新 熱修復
Flutter結構
FrameWork層
Engine層 skia、Dart(DartRuntime,GC、JIT(debug下)、Text
Flutter Application: Flutter的終端應用
Flutter Module: Flutter模塊 原生的Android或者IOS能夠引入Flutter Module進行混合開發
Flutter Plugin: 封裝原生的Android或者IOS 提供API給Flutter使用
Flutter Package: 純Dart語言的組件 如自定義Widget
Flutter Application
目錄結構:
/android Android項目 能夠只打開這個項目
有個 io.flutter.plugins的目錄 裏面有 GeneratedPluginRegistrant
用於
/ios IOS項目 能夠只打開這個項目
/.lib 存放dart的代碼
C和dart通訊
FFI
DynamicLibrary.open 加載動態庫
funtion func = xxLibrary.lookup
去動態庫找到指定的函數
將C的函數轉爲dart的function
怎麼與native通訊
Flutter與Android交互原理
1、FlutterActivity
FlutterView getFlutterView()
1 FlutterView extends SurfaceView
經過skia渲染引擎
2 FlutterActivityDelegate
addContentView 將FlutterView加入到Activity中
2、FlutterApplication
經過FlutterMain.java 加載flutter.so flutter的config AOT 和 Resource
編譯Dart生成了snapshot(相似jar包)經過函數main作入口
最終生成flutter.jar?
怎麼調native API
怎麼依附於Activity
怎麼打成包
Dart
靜態強類型
沒有null檢查
能夠AOT能夠JIT
直接編譯成本地代碼 不須要JS那種的橋 形成上下文頻繁的切換 各類保留現場的狀態保存 所以啓動速度和運行速度快
UI也是直接繪製的 性能高
Dart 避免了搶佔式調度和共享內存(於是也不須要鎖)
isolate 單線程模型
isolate是Dart對actor併發模式的實現。運行中的Dart程序由一個或多個actor組成,這些actor也就是Dart概念裏面的isolate。isolate是有本身的內存和單線程控制的運行實體。isolate自己的意思是「隔離」,由於isolate之間的內存在邏輯上是隔離的。isolate中的代碼是按順序執行的,任何Dart程序的併發都是運行多個isolate的結果。由於Dart沒有共享內存的併發,沒有競爭的可能性因此不須要鎖,也就不用擔憂死鎖的問題
root isolate進行UI處理
isolate間的通訊
管道:ReceivePort與SendPort一塊兒,是隔離區之間惟一的通訊方式
isolate與普通線程的區別
咱們能夠看到isolate神似Thread,但實際上二者有本質的區別。操做系統內的線程之間是能夠有共享內存的而isolate沒有,這是最爲關鍵的區別
dart2js 編譯器能夠將dart代碼直接生成js代碼 運行在web中
Dart VM
界面跳轉
經過Navigator棧統一管理界面的跳轉
Router路由的概念 每一個界面都是一個Router
使用:
經過一個自定義路由命名進行區分跳轉,這樣更清晰
Router.pushNoParams(BuildContext context, String url) { Navigator.push(context, MaterialPageRoute(builder: (context) { return _getPage(url, null); })); } Router.push(BuildContext context, String url, dynamic params) { Navigator.push(context, MaterialPageRoute(builder: (context) { return _getPage(url, params); })); } static const secondPage = 'app://SecondPage'; Widget _getPage(String url, dynamic params) { if (url.startsWith('https://') || url.startsWith('http://')) { return WebViewPage(url, params: params); } else { switch (url) { case secondPage: return SecondPage(params); 退出調用 Router.pop()便可
若要傳遞參數 則構造函數的參數裏面攜帶就好
Flutter inspector
Flutter API設計理念
1 Compose not complect 組合而非交織
2 層級式設計
高層API要包裹好底層API 不要實現斷崖式設計
即底層API不須要對外暴露 給外邊調用或者實現
Flutter命令
是否將輸出內容着色顯示,在終端,--color是默認值;不然,--no-color是默認值 // 下載相應的flutter庫 flutter packages get // dart的pub命令參考:https://dart.cn/tools/pub/cmd // 從命令行運行腳本 // global: 不存在於當前 Package 中的可執行對象 // [arg1] [arg2]爲腳本的參數 flutter pub [global] run xx [arg1] [arg2] // 刪除`build/`和`.dart_tool/`目錄,清除緩存信息,避免以前不一樣版本代碼的影響 flutter clean // 安裝包到設備上 flutter install // 運行應用 flutter run
flutter常見文件
pubspec.yaml
添加庫依賴的
有^的第一次會下載最新版本的
dependencies: flutter: sdk: flutter flutter_localizations: sdk: flutter intl: ^0.16.1
pubspec.lock
文件中描述的就是你各類依賴包的真實版本和下載地址。固然還有lock的做用,當你下次刷新項目時,pub get會根據lock中的描述去獲取依賴包。即便有新的版本也不會跟新到。此時能夠經過 pub upgrade來更新
Flutter常見錯誤
1 Process ‘command ‘/Users/maxshwu/project/FlutterSDK/flutter/bin/flutter’’ finished with non-zero exit value 1
解決: 看Dart Analysis中的dart錯誤
2 Cause: assert pluginDirectory.exists()
緣由: 刪掉了plugin後報的錯
解決: 將相關使用plugin的地方刪掉
flutter clean
flutter packages get 去下載相應的flutter庫
3 Another exception was thrown: NoSuchMethodError: The method ‘-’ was called on null.
能夠搜索一下(The relevant error-causing widget was:)看看是哪一個控件可能出現的問題(也有多是這個控件的子控件的問題)
如:The method ‘[]’ was called on null
緣由: 調用[]的對象是空的
解決: 給這個對象作好判空處理
如:The method ‘-’ was called on null
緣由:
1 column嵌套了Row
2 Row嵌套了非標誌/非合理的Widget
解決:
1 給row加一層佈局
2 使用系統控件或者標誌的自定義控件
4 error: The name ‘Image’ is defined in the libraries ‘package:flutter/src/widgets/image.dart’ and ‘package:image/src/image.dart’. — ambiguous_import
緣由: 兩個import的文件都包含了這個類,多重定義了
解決: import ‘package:flutter/src/widgets/image.dart’ as MyImg;
MyImg.xxx()
5 No active package intl_utils.
pub global activate intl_utils
6 Entrypoint isn’t within a Flutter pub root
1 https://stackoverflow.com/questions/57000043/error-entrypoint-isnt-within-the-current-project
2 將gtest和gmock從項目中移除
7 點擊Flutter Attach 以後長時間不能連接到設備
flutter docotr -v 診斷下 看是否代理問題
export NO_PROXY=localhost,127.0.0.1
8 Could not resolve the package ‘xxx’ in ‘xxx/xxx.dart’. 1 flutter packages get 2 從新build一下flutter的module flutter build aar