Flutter(一)介绍、Dart语言简介

news/2024/12/4 6:59:49/

Flutter介绍

纯原生开发主要面临动态化更新和开发成本两个问题,而针对这两个问题,诞生了一些跨平台的动态化框架

跨平台技术简介

在这里插入图片描述
Flutter 是 Google 推出并开源的移动应用开发框架,主打跨平台、高保真、高性能。开发者可以通过 Dart 语言开发 App,一套代码同时运行在 iOS 和 Android平台

1. 跨平台自绘引擎

Flutter 既不使用 WebView,也不使用操作系统的原生控件。 相反,Flutter 使用自己的Skia来绘制 Widget(组件)。这样不仅可以保证在 Android 和iOS 上 UI 的一致性,也可以避免对原生控件依赖而带来的限制及高昂的维护成本。

目前 Google Chrome浏览器和 Android 均采用 Skia 作为其 2D 绘图引擎。

目前 Flutter 已经支持 iOS、Android、Web、Windows、macOS、Linux、Fuchsia(Google新的自研操作系统)等众多平台

2. 高性能

Flutter APP 采用 Dart 语言开发。Dart 在 JIT(即时编译)模式下,执行速度与 JavaScript 基本持平。但是 Dart 支持 AOT,当以 AOT模式运行时,JavaScript 便远远追不上了

Flutter 使用自己的渲染引擎来绘制 UI ,布局数据等由 Dart 语言直接控制,所以在布局过程中不需要像 RN 那样要在 JavaScript 和 Native 之间通信

Flutter 为什么选择 Dart 语言?

1.开发效率高。

Flutter 在开发阶段采用,采用 JIT 模式,这样就避免了每次改动都要进行编译,极大的节省了开发时间;

Flutter 在发布时可以通过 AOT 生成高效的机器码以保证应用性能。而 JavaScript 则不具有这个能力。

2.高性能。

Flutter 旨在提供流畅、高保真的的 UI 体验,而 Dart 支持 AOT,在这一点上可以做的比 JavaScript 更好。

3.快速内存分配。

Flutter 框架使用函数式流,这使得它在很大程度上依赖于底层的内存分配器,而 Dart 也正好满足。

4.类型安全和空安全。

由于 Dart 是类型安全的语言,所以 Dart 支持静态类型检测,可以在编译前发现一些类型的错误,并排除潜在问题。

5.Dart 团队就在你身边。

由于有 Dart 团队的积极投入,Flutter 团队可以获得更多、更方便的支持Dart VM 之前已经针对吞吐量进行了优化,但团队现在正在优化 VM 的延迟时间,这对于 Flutter 的工作负载更为重要。

Flutter框架结构

在这里插入图片描述
Flutter 从上到下可以分为三层:框架层、引擎层和嵌入层

框架层:纯 Dart实现的 SDK,它实现了一套基础库

引擎层:主要是 C++ 实现,包括 Skia 引擎、Dart 运行时、文字排版引擎等

嵌入层:嵌入层采用了当前平台的语言编写,例如 Android 使用的是 Java 和 C++, iOS 和 macOS 使用的是 Objective-C 和 Objective-C++,Windows 和 Linux 使用的是 C++

Flutter 代码可以通过嵌入层,以模块方式集成到现有的应用中,也可以作为应用的主体

Dart语言简介

1.变量声明

var

Dart 中 var 变量一旦赋值,类型便会确定,则不能再改变其类型

var t = "hi world";
// 下面代码在dart中会报错,因为变量t的类型已经确定为String,
// 类型一旦确定后则不能再更改其类型。
t = 1000;

dynamic与Object

dynamic与Object声明的变量都可以赋值任意对象,且后期可以改变赋值的类型,不同的是dynamic声明的对象编译器会提供所有可能的组合,而Object声明的对象只能使用 Object 的属性与方法, 否则编译器会报错

dynamic a;Object b = "";main() {a = "";printLengths();}   printLengths() {// 正常
print(a.length);// 报错 The getter 'length' is not defined for the class 'Object'print(b.length);}

final 或 const

不可更改变量,使用 final 或 const,两者区别在于:const 变量是一个编译时常量(编译时直接替换为常量值),final变量在第一次使用时被初始化。被final或者const修饰的变量,变量类型可以省略

//可以省略String这个类型声明
final str = "hi world";
//final String str = "hi world"; 
const str1 = "hi world";
//const String str1 = "hi world";

空安全(null-safety)

int i = 8; //默认为不可空,必须在定义时初始化。
int? j; // 定义为可空类型,对于可空变量,我们在使用前必须判空。// 如果我们预期变量不能为空,但在定义时不能确定其初始值,则可以加上late关键字,
// 表示会稍后初始化,但是在正式使用它之前必须得保证初始化过了,否则会报错
late int k;
k=9;

2.函数

Dart函数声明如果没有显式声明返回值类型时会默认当做dynamic处理,函数返回值没有类型推断,函数可作为变量,可作为参数

device是可选参数

String say(String from, String msg, [String? device]) {}

使用{param1, param2, …},放在参数列表的最后面,用于指定命名参数

void enableFlags({bool bold, bool hidden}) {// ... 
}

调用

enableFlags(bold: true, hidden: false);

Dart 是不支持多继承的,但是它支持 mixin,简单来讲 mixin 可以 “组合” 多个类

定义了几个 mixin,然后通过 with 关键字将它们组合成不同的类。有一点需要注意:如果多个mixin 中有同名方法,with 时,会默认使用最后面的 mixin 的

class Person {say() {print('say');}
}mixin Eat {eat() {print('eat');}
}mixin Walk {walk() {print('walk');}
}mixin Code {code() {print('key');}
}class Dog with Eat, Walk{}
class Man extends Person with Eat, Walk, Code{}

3.异步支持

Dart类库有非常多的返回Future或者Stream对象的函数。 这些函数被称为异步函数:它们只会在设置好一些耗时操作之后返回,比如像 IO操作。而不是等到这个操作完成。

async和await关键词支持了异步编程,允许您写出和同步代码很像的异步代码

Future.then

2秒后返回结果字符串"hi world!",然后我们在then中接收异步结果并打印结果

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

Future.catchError和onError

异步任务发生错误,我们可以在catchError中捕获错误

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

Future.whenComplete

无论异步任务执行成功或失败都需要做一些事的场景,比如在网络请求前弹出加载对话框,在请求结束后关闭对话框。这种场景,有两种方法,
第一种是分别在then或catch中关闭一下对话框,
第二种就是使用Future的whenComplete回调

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

Future.wait

等待多个异步任务都执行结束后才进行一些操作,比如我们有一个界面,需要先分别从两个网络接口获取数据,获取成功后,我们需要将两个接口数据进行特定的处理后再显示到UI界面上

//只有数组中所有Future都执行成功后,才会触发then的成功回调,只要有一个Future执行失败,就会触发错误回调
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);
});

async/await

Dart中的async/await 和JavaScript中的async/await功能是一样的:异步任务串行化

如果代码中有大量异步逻辑,并且出现大量异步任务依赖其他异步任务的结果时,必然会出现Future.then回调中套回调情况。

比如现在有个需求场景是用户先登录,登录成功后会获得用户ID,然后通过用户ID,再去请求用户个人信息,获取到用户个人信息后,为了使用方便,我们需要将其缓存在本地文件系统,代码如下:

//先分别定义各个异步任务
Future<String> login(String userName, String pwd){...//用户登录
};
Future<String> getUserInfo(String id){...//获取用户信息 
};
Future saveUserInfo(String userInfo){...// 保存用户信息 
}; 
login("alice","******").then((id){//登录成功后通过,id获取用户信息    getUserInfo(id).then((userInfo){//获取用户信息后保存 saveUserInfo(userInfo).then((){//保存用户信息,接下来执行其他操作...});});
})

这个问题被形象的称为回调地狱

消除回调地狱
一、使用Future消除Callback Hell

login("alice","******").then((id){return getUserInfo(id);
}).then((userInfo){return saveUserInfo(userInfo);
}).then((e){//执行接下来的操作 
}).catchError((e){//错误处理  print(e);
});

Future 的所有API的返回值仍然是一个Future对象,所以可以很方便的进行链式调用” ,如果在then 中返回的是一个Future的话,该future会执行,执行结束后会触发后面的then回调,这样依次向下,就避免了层层嵌套

二、使用 async/await 消除 callback hell
通过Future回调中再返回Future的方式虽然能避免层层嵌套,但是还是有一层回调,有没有一种方式能够让我们可以像写同步代码那样来执行异步任务而不使用回调的方式?答案是肯定的,这就要使用async/await了

task() async {try{String id = await login("alice","******");String userInfo = await getUserInfo(id);await saveUserInfo(userInfo);//执行接下来的操作   } catch(e){//错误处理   print(e);   }  
}

Stream

Stream 也是用于接收异步事件数据,和 Future 不同的是,它可以接收多个异步操作的结果(成功或失败)。 也就是说,在执行异步任务时,可以通过多次触发成功或失败事件来传递结果数据或错误异常。 Stream 常用于会多次读取数据的异步任务场景,如网络内容下载、文件读写等

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: (){});

输出

I/flutter (17666): hello 1
I/flutter (17666): Error
I/flutter (17666): hello 3

http://www.ppmy.cn/news/24771.html

相关文章

零基础学MySQL(五)-- 详细讲解数据库中的常用函数

目录&#x1f387;一、聚合函数1️⃣count 函数&#xff08;1&#xff09;基本语法&#xff08;2&#xff09;基本练习&#xff08;3&#xff09;注意细节2️⃣sum 函数&#xff08;1&#xff09;基本语法&#xff08;2&#xff09;基本练习&#xff08;3&#xff09;注意细节3…

vue-router路由配置

介绍&#xff1a;路由配置主要是用来确定网站访问路径对应哪个文件代码显示的&#xff0c;这里主要描述路由的配置、子路由、动态路由&#xff08;运行中添加删除路由&#xff09; 1、npm添加 npm install vue-router // 执行完后会自动在package.json中添加 "vue-router…

Hive手册

文章目录1 Hive基本概念1.1 Hive简介1.1.1 什么是Hive1.1.2 为什么使用Hive1.1.3 Hive特点1.2 Hive的体系架构1.3 Hive和RDBMS的对比1.4 Hive的数据存储2 Hive基本使用2.1 Hive存储格式2.2 Hive中的数据模型3 Hive应用3.1 Hive内置函数3.2 SQL介绍与Hive应用场景3.2.1 数据库操…

数模美赛如何找数据 | 2023年美赛数学建模必备数据库

2023美赛资料分享/思路答疑群&#xff1a;322297051 欧美相关统计数据&#xff08;一般美赛这里比较多&#xff09; 1、http://www.census.gov/ 美国统计局&#xff08;统计调查局或普查局&#xff09;官方网站 The Census Bureau Web Site provides on-line access to our …

leetcode练习一:数组(二分查找、双指针、滑动窗口)

文章目录一、 数组理论基础二、 二分查找2.1 解题思路2.2 练习题2.2.1 二分查找(题704)2.2.2 搜索插入位置&#xff08;题35&#xff09;2.2.3 查找排序数组元素起止位置&#xff08;题34&#xff09;2.2.4 有效的完全平方数&#xff08;题367&#xff09;2.2.5 x 的平方根&…

“华为杯”研究生数学建模竞赛2006年-【华为杯】C题:维修线性流量阀时的内筒设计问题(附获奖论文及matlab代码)

赛题描述 油田采油用的油井都是先用钻机钻几千米深的孔后,再利用固井机向四周的孔壁喷射水泥砂浆得到水泥井管后形成的。固井机上用来控制砂浆流量的阀是影响水泥井管质量的关键部件,但也会因磨损而损坏。目前我国还不能生产完整的阀体,固井机仍依赖进口。由于损坏的内筒已…

两种特征提取方法与深度学习方法对比的小型金属物体分类分析研究

本文讨论了用于对包括螺丝、螺母、钥匙和硬币在内的小型金属物体进行分类的两种特征提取方法的效率&#xff1a;定向梯度直方图 (HOG) 和局部二进制模式 (LBP)。首先提取标记图像的所需特征并以特征矩阵的形式保存。使用三种不同的分类方法&#xff08;非参数 K 最近邻算法、支…

Web自动化测试——selenium篇(二)

文章目录一、浏览器相关操作二、键盘操作三、鼠标操作四、弹窗操作五、下拉框选择六、文件上传七、错误截图一、浏览器相关操作 浏览器窗口大小设置 driver.manage().window().maximize();//窗口最大化 driver.manage().window().minimize();//窗口最小化 driver.manage().wi…