学习《flutter 实战》 认真版 第一章

原生开发

主要优势:可访问平台全部功能(GPS、摄像头);速度快、性能高、可以实现复杂动画及绘制,整体用户体验好。
主要缺点:平台特定,开发成本高;不同平台必须维护不同代码,人力成本随之变大;内容固定,动态弱化,大多数情况下,有新功能更新时只能发版。
所以纯原生开发主要面临动态化和开发成本两个问题。

跨平台技术

H5 + 原生

主要原理就是将App中需要动态变动的内容通过H5来实现,通过原生的网页加载空间WebView或WKWebView来加载的开发模式为混合开发。
小程序,目前国内各家公司小程序应用层的开发技术栈是Web技术栈,而底层渲染方式基本都是WebView和原生相结合的方式。
混合框架,原生代码中预先实现一些访问系统能力的API,然后暴露给WebView供JavaScript调用。WebView中JavaScript和原生API的通信桥梁为JsBridge。

小结:
动态内容可以用 H5开发,而H5是Web 技术栈,Web技术栈生态开放且社区资源丰富,整体开发效率高。
缺点是性能体验不佳,对于复杂用户界面或动画,WebView 有时会不堪重任。
React Native、Weex

React Native(RN)使用JSX语言(扩展后的JavaScript,主要是可以在JavaScript中写HTML标签)和CSS来开发移动应用。
React的重要思想:状态改变则UI随之自动改变。

React响应式原理:
开发者只需要关注转移(数据),当状态发生变化,React框架会自动根据新的状态重新构建UI。
React框架在接收到用户状态改变通知后,会根据当前渲染树,结合最新的状态改变,通过diff算法,计算出树中变化的部分,然后只更新变化的部分,从而避免整颗树重构,提高性能。

在状态变化后React框架并不会立即去计算并渲染DOM树的变化部分,相反,React会在DOM树的基础上建立一个抽象层,虚拟DOM树,对数据和状态所做的任何改动,都会被自动且高效的同步到虚拟DOM,最后再批量同步到真实DOM中,而不是每次改变都去操作DOM。原因是浏览器中每一次DOM操作都有可能引起浏览器的重绘和回流( 重新排版布局,确定DOM节点的大小和位置)。浏览器的重绘和回流都是比较昂贵的操作,会带来性能问题。

思考:Diff操作和DOM批量更新难道不应该是浏览器的职责吗?第三方框架中去做合不合适?
答: Diff操作和DOM批量更新是前端开发中常见的任务,确实是浏览器的职责之一。浏览器负责解析HTML、CSS,并将它们渲染成可交互的网页。然而,由于不同浏览器的实现和性能表现存在差异,以及现代前端应用对复杂交互和实时更新的需求,第三方框架通常被用来提供更高效、灵活和一致的解决方案。

使用第三方框架来处理Diff操作和DOM批量更新具有以下优势:

性能优化:第三方框架通常会针对不同浏览器的特性和性能进行优化,提供更高效的Diff算法和DOM更新策略。

抽象复杂性:前端框架通过封装Diff操作和DOM更新过程,提供更简洁、高级的API,使开发者能够专注于业务逻辑而不必过分关注底层细节。

跨浏览器兼容性:第三方框架可以屏蔽不同浏览器之间的差异,提供一致的行为和兼容性,简化跨浏览器开发。

功能丰富:许多第三方框架提供了额外的功能,如状态管理、组件化开发、路由管理等,可以进一步提高开发效率和代码质量。

虽然浏览器本身应该负责Diff操作和DOM批量更新,但使用第三方框架来处理这些任务是合适的,并且在现代前端开发中非常常见。它们可以提供更好的性能、抽象复杂性、兼容性和功能,使开发者能够更快速、高效地构建复杂的前端应用程序。
 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。原文链接:https://blog.csdn.net/qq_53163443/article/details/132297491

React Native是React在原生移动应用平台的衍生产物,区别在于虚拟DOM映射的对象不同。React中虚拟DOM最终会映射为浏览器DOM树,而RN中虚拟DOM会通过JavaScriptCore映射为原生控件。

JavaScriptCore在RN中的作用:
为JavaScript提供运行环境
是JavaScript与原生应用之间通信的桥梁,作用和JsBridge一样。 

而 RN 中将虚拟 DOM 映射为原生控件的过程主要分两步:
1、布局消息传递; 将虚拟 DOM 布局信息传递给原生;
2、原生根据布局信息通过对应的原生控件渲染;

	小结:
 JavaScript 开发 + 原生渲染 的方式主要优点如下:
1、采用 Web 开发技术栈,社区庞大、上手快、开发成本相对较低。
2、原生渲染,性能相比 H5 提高很多。
3、动态化较好,支持热更新。
不足:
1、渲染时需要 JavaScript 和原生之间通信,在有些场景如拖动可能会因为通信频繁导致卡顿。
2、JavaScript 为脚本语言,执行时需要解释执行 (这种执行方式通常称为 JIT,即 Just In Time,指在执行时实时生成机器码),执行效率和编译类语言(编译类语言的执行方式为 AOT ,即 Ahead Of Time,指在代码执行前已经将源码进行了预处理,这种预处理通常情况下是将源码编译为机器码或某种中间码)仍有差距。
3、由于渲染依赖原生控件,不同平台的控件需要单独维护,并且当系统更新时,社区控件可能会滞后;除此之外,其控件系统也会受到原生UI系统限制,例如,在 Android 中,手势冲突消歧规则是固定的,这在使用不同人写的控件嵌套时,手势冲突问题将会变得非常棘手。这就会导致,如果需要自定义原生渲染组件时,开发和维护成本过高。

Flutter

Flutter 移动应用开发框架,主打跨平台、高保真、高性能。使用Dart语言,一套代码同时运行在ios和Android平台。并且提供了丰富的组件、接口,并且可以和平台语言混合开发。

1、跨平台自绘引擎
flutter使用自己的高性能渲染引擎来和绘制widget。保证多平台上ui一致,也可以避免对原生控件依赖而带来的限制及高昂的维护成本。
底层使用Skia作为其2D渲染引擎,可以更加高效能且简洁。
2、高性能
第一:Flutter App 采用 Dart 语言开发。Dart 在 JIT(即时编译)模式下,执行速度与 JavaScript 基本持平。但是 Dart 支持 AOT,当以 AOT模式运行时,JavaScript 便远远追不上了。执行速度的提升对高帧率下的视图数据计算很有帮助。

第二:Flutter 使用自己的渲染引擎来绘制 UI ,布局数据等由 Dart 语言直接控制,所以在布局过程中不需要像 RN 那样要在 JavaScript 和 Native 之间通信,这在一些滑动和拖动的场景下具有明显优势,因为在滑动和拖动过程往往都会引起布局发生变化,所以 JavaScript 需要和 Native 之间不停地同步布局信息,这和在浏览器中JavaScript 频繁操作 DOM 所带来的问题是类似的,都会导致比较可观的性能开销。

3、采用Dart语言开发
优点:
a.开发效率高。
Dart 运行时和编译器支持 Flutter 的两个关键特性的组合:
基于 JIT 的快速开发周期:Flutter 在开发阶段采用 JIT 模式,这样就避免了每次改动都要进行编译,极大地节省了开发时间;
基于 AOT 的发布包: Flutter 在发布时可以通过 AOT 生成高效的机器码以保证应用性能。而 JavaScript 则不具有这个能力。

b.高性能。
Flutter 旨在提供流畅、高保真的 UI 体验。为了实现这一点,Flutter 中需要能够在每个动画帧中运行大量的代码。这意味着需要一种既能保证高性能,也不会出现丢帧的编程语言,而 Dart 支持 AOT,在这一点上可以做得比 JavaScript 更好。

c.快速内存分配。
Flutter 框架使用函数式流,这使得它在很大程度上依赖于底层的内存分配器。因此,拥有一个能够有效地处理琐碎任务的内存分配器将显得十分重要,在缺乏此功能的语言中,Flutter 将无法有效地工作。当然 Chrome V8 的 JavaScript 引擎在内存分配上也已经做的很好,事实上 Dart 开发团队的很多成员都是来自Chrome 团队的,所以在内存分配上 Dart 并不能作为超越 JavaScript 的优势,而对于Flutter来说,它需要这样的特性,而 Dart 也正好满足而已。

d.类型安全和空安全。

由于 Dart 是类型安全的语言,且 2.12 版本后也支持了空安全特性,所以 Dart 支持静态类型检测,可以在编译前发现一些类型的错误,并排除潜在问题,这一点对于前端开发者来说可能会更具有吸引力。与之不同的,JavaScript 是一个弱类型语言,也因此前端社区出现了很多给 JavaScript 代码添加静态类型检测的扩展语言和工具,如:微软的 TypeScript 以及Facebook 的 Flow。相比之下,Dart 本身就支持静态类型,这是它的一个重要优势。

Flutter 框架结构

框架层

Flutter Framework
底下两层(Foundation 和 Animation、Painting、Gestures)在 Google 的一些视频中被合并为一个dart UI层,对应的是Flutter中的dart:ui包,它是 Flutter Engine 暴露的底层UI库,提供动画、手势及绘制能力。

Rendering 层,即渲染层,这一层是一个抽象的布局层,它依赖于 Dart UI 层,渲染层会构建一棵由可渲染对象组成的渲染树,当动态更新这些对象时,渲染树会找出变化的部分,然后更新渲染。渲染层可以说是Flutter 框架层中最核心的部分,它除了确定每个渲染对象的位置、大小之外还要进行坐标变换、绘制(调用底层 dart:ui )。

Widgets 层是 Flutter 提供的一套基础组件库,在基础组件库之上,Flutter 还提供了 Material 和 Cupertino 两种视觉风格的组件库,它们分别实现了 Material 和 iOS 设计规范。

引擎层

Engine,即引擎层。毫无疑问是 Flutter 的核心, 该层主要是 C++ 实现,其中包括了 Skia 引擎、Dart 运行时(Dart runtime)、文字排版引擎等。在代码调用 dart:ui库时,调用最终会走到引擎层,然后实现真正的绘制和显示。

嵌入层

Embedder,即嵌入层。Flutter 最终渲染、交互是要依赖其所在平台的操作系统 API,嵌入层主要是将 Flutter 引擎 ”安装“ 到特定平台上。嵌入层采用了当前平台的语言编写,例如 Android 使用的是 Java 和 C++, iOS 和 macOS 使用的是 Objective-C 和 Objective-C++,Windows 和 Linux 使用的是 C++。 Flutter 代码可以通过嵌入层,以模块方式集成到现有的应用中,也可以作为应用的主体。Flutter 本身包含了各个常见平台的嵌入层,假如以后 Flutter 要支持新的平台,则需要针对该新的平台编写一个嵌入层。

Dart

var 关键字
可以接收任何类型的变量,一旦赋值,类型便会确定,则不能再改变其类型。

dynamic 和object
Object是Dart所有对象的根基类,所有类型都是Object的子类(包括Function和Null),所以任何类型的数据都可以赋值给Object声明的对象。
dynamic声明的变量也可以赋值任意对象,且后期可以改变赋值的类型。与Object不同的是dynamic声明的对象编译器会提供所有可能的组合,而Object声明的对象只能使用Object的属性和方法,否则会编译出错。

final和const
final变量必须在第一次使用时被初始化
const变量是一个编译时常量

空安全
有个空安全,则定义变量时我们可以指定变量是可空还是不可空

int? j;

通过在变量后面加一个“!",可以在变量为可空类型时,告诉预处理器它已经不是null了。

print(i! * 8)

函数
Dart是一种真正的面向对象的语言,所以即使是函数也是对象,并且有一个类型Function。
1、可选的位置参数
用[]标记为可选的位置参数,并放在参数列表最后头。
2、可选的命名参数
定义函数时,使用{},放在参数列表的最后面,用于指定命名参数。

mixin
mixin可以“组合”多个类。如果多个mixin中有同名方法,with时,会默认使用最后面的mixi的,mixin方法中可以通过super关键字调用之前mixin或类中的方法。

异步支持
1、Future
表示一个异步操作的最终完成及其结果值的表示。
Future.then

Future.delayed(Duration(seconds: 2),(){
   return "hi world!";
}).then((data){
   print(data);
});

Future.catchError

Future.delayed(Duration(seconds: 2),(){
   //return "hi world!";
   throw AssertionError("Error");  
}).then((data){
   //执行成功会走到这里  
   print("success");
}).catchError((e){
   //执行失败会走到这里  
   print(e);
});

Future.whenComplete

Future.delayed(Duration(seconds: 2),(){
   //return "hi world!";
   throw AssertionError("Error");
}).then((data){
   //执行成功会走到这里 
   print(data);
}).catchError((e){
   //执行失败会走到这里   
   print(e);
}).whenComplete((){
   //无论成功或失败都会走到这里
});

Future.wait

Future.wait([
  // 2秒后返回结果  
  Future.delayed(Duration(seconds: 2), () {
    return "hello";
  }),
  // 4秒后返回结果  
  Future.delayed(Duration(seconds: 4), () {
    return " world";
  })
]).then((results){
  print(results[0]+results[1]);
}).catchError((e){
  print(e);
});

Stream
Stream也是用于接收异步事件数据,和Future不同的是,它可以接收多个异步操作的结果。

Stream.fromFutures([
  // 1秒后返回结果
  Future.delayed(Duration(seconds: 1), () {
    return "hello 1";
  }),
  // 抛出一个异常
  Future.delayed(Duration(seconds: 2),(){
    throw AssertionError("Error");
  }),
  // 3秒后返回结果
  Future.delayed(Duration(seconds: 3), () {
    return "hello 3";
  })
]).listen((data){
   print(data);
}, onError: (e){
   print(e.message);
},onDone: (){

});
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值