Flutter介绍与基本使用

蓝咒 提交于 2020-10-18 10:47:50

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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!