Flutter介绍与基本使用
一、 环境以及工具的准备
1 下载Flutter SDK
https://flutter.dev/docs/get-started/install/macos
并将其bin路径加入系统路径中
IDE使用
AndroidStudio使用Flutter
Android Studio 安装插件 Flutter和Dart插件
GeneratedPluginRegistrant 将Android的Activity注册给Flutter
FlutterActivity/FlutterAppDelegate,是Android的Plugin管理器,它记录了所有的Plugin,并将Plugin绑定到FlutterView/FlutterViewController
Flutter inspector
Flutter Outline
Flutter Performance
XCode
VS Code运行Dart
安装Dart SDK
brew tap dart-lang/dart
brew install dart
dart --version
VS Code安装插件
Dart 和 Code Runner插件
3
二、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交互原理
一、FlutterActivity
FlutterView getFlutterView()
1 FlutterView extends SurfaceView
通过skia渲染引擎
2 FlutterActivityDelegate
addContentView 将FlutterView加入到Activity中
二、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
来源:oschina
链接:https://my.oschina.net/u/4277346/blog/4678312