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

news2024/9/23 7:23:29

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.coloradmin.cn/o/342858.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【云原生kubernetes】k8s service使用详解

一、什么是服务service&#xff1f; 在k8s里面&#xff0c;每个Pod都会被分配一个单独的IP地址,但这个IP地址会随着Pod的销毁而消失&#xff0c;重启pod的ip地址会发生变化&#xff0c;此时客户如果访问原先的ip地址则会报错 &#xff1b; Service (服务)就是用来解决这个问题的…

Django设计模式以及模板层介绍

MVC和MTV 传统的MVC作用&#xff1a;降低模块间的耦合度&#xff08;解耦&#xff09;Django的MTV模式 作用&#xff1a;降低模块间的耦合度&#xff08;解耦&#xff09;什么是模板 1、模板是可以根据字典数据动态变化的html网页2、模板可以根据视图中传递的字典数据动态生成相…

AtCoder Grand Contest 061(题解)

A - Long Shuffle 这道题本质是一个找规律的题 既然是打表题&#xff0c;我们先暴力把他打出来 (盗一张图.jpg) 接下来就是在这张图中挖掘答案 我们可以明显的看到偶数行是有一些规律的 要么是相邻对的互换&#xff0c;要么不变 不变和互换的位置也有讲究&#xff0c;在二进制…

DS期末复习卷(四)

一、选择题(每题1分共 20分) 1&#xff0e;设一维数组中有n个数组元素&#xff0c;则读取第i个数组元素的平均时间复杂度为&#xff08;C &#xff09;。 (A) O(n) (B) O(nlog2n) © O(1) (D) O(n2) 数组读取元素的时间复杂度为O&#xff08;1&#xff09; 2&#xff0e;设…

SpringCloud Alibaba

文章目录&#x1f68f; 第十七章 SpringCloud Alibaba入门简介&#x1f6ac; 一、为什么使用Alibaba&#x1f6ad; 1、spring netflix进入维护模式&#x1f6ad; Spring cloud alibaba&#x1f6ac; 二、如何使用&#xff1f;&#x1f6ac; 三、版本对应&#x1f68f; 第十八章…

Jmeter接口测试+压力测试

jmeter是apache公司基于java开发的一款开源压力测试工具&#xff0c;体积小&#xff0c;功能全&#xff0c;使用方便&#xff0c;是一个比较轻量级的测试工具&#xff0c;使用起来非常简单。因为jmeter是java开发的&#xff0c;所以运行的时候必须先要安装jdk才可以。jmeter是免…

朴素贝叶斯算法和拉普拉斯平滑详细介绍及其原理详解

相关文章 K近邻算法和KD树详细介绍及其原理详解朴素贝叶斯算法和拉普拉斯平滑详细介绍及其原理详解 文章目录相关文章前言一、朴素贝叶斯算法二、拉普拉斯平滑总结前言 今天给大家带来的主要内容包括&#xff1a;朴素贝叶斯算法、拉普拉斯平滑。这些内容也是机器学习的基础内容…

AXI-Lite 学习笔记

AXI-Lite 学习笔记 参考 FPGA&#xff1a;AXI_Lite总线基础2-1]、第二节 AXI总线介绍、ZYNQ PL与PS交互专题_哔哩哔哩_bilibili AXI-Lite总线系列1 - 基础知识_哔哩哔哩_bilibili AXI4 介绍 AXI4 是ARM公司提出的一种片内总线&#xff0c;描述了主从设备之间的数据传输方式。主…

深入浅出原核基因表达调控(乳糖操纵子、色氨酸操纵子)

原核基因表达调控 前言 自然界里&#xff0c;能量时有时无&#xff0c;各种生命为了让自己能够活下去&#xff0c;需要适应环境&#xff0c;在不同的环境合成不同的蛋白质。 原核生物体内有很多细胞&#xff0c;细胞里面有很多蛋白质&#xff0c;但是这些蛋白质在这些细胞里…

React Draggable插件实现拖拽功能

React Draggable插件实现拖拽功能1.下载Draggable插件2.引入Draggable插件3.设置一个div&#xff0c;并设置样式&#xff0c;并用Draggable包裹起来4.设置拖拽的范围5.Draggable常用props1.下载Draggable插件 npm install react-draggable2.引入Draggable插件 // 引入拖拽插件…

浅谈指向二维数组元素的指针变量

(1)指向数组元素的指针变量 例1.有一个3X4的二维数组,要求用指向元素的指针变量输出二维数组各元素的值. 编写程序 1 #include <stdio.h>2 int main()3 {4 int a[3][4] { 1,3,5,7,9,11,13,15,17,19,21,23 };5 int *p;6 for (p a[0]; p < a[0] 12; p) …

sni+tomcat漏洞复现

sni SNI产生背景 SSL以及TLS&#xff08;SSL的升级版&#xff09;为客户端与服务器端进行安全连接提供了条件。但是&#xff0c;由于当时技术限制&#xff0c;SSL初期的设计顺应经典的公钥基础设施 PKI(Public Key Infrastructure)设计&#xff0c;PKI 认为一个服务器只为一个…

SpringBoot简单集成OpenFeign

问题 在SpringBoot中简单集成Feign&#xff0c;不想使用Rest Temple了。 步骤 Maven <properties><spring.cloud-version>2022.0.1</spring.cloud-version></properties> <dependencyManagement><dependencies><dependency><g…

javaEE 初阶 — 连接管理机制

文章目录连接管理机制1. 建立连接&#xff08;三次握手&#xff09;2. 断开连接&#xff08;四次挥手&#xff09;TCP 的工作机制确认应答机制 超时重传机制 连接管理机制 比如 主机A 的空间存储了 主机B 的 ip 和 端口&#xff0c;主机B 的空间存储了 主机A 的 ip 和 端口。…

autoCAD2022 - 设置新的原点

文章目录autoCAD2022 - 设置新的原点概述笔记UCS原点设置功能的菜单位置ENDautoCAD2022 - 设置新的原点 概述 上次整板子的dxf时, 原来的原点不合适, 想调整一下. 当时整完了, 没记录. 这次用的时候, 又找半天… 设置新原点的功能, 不在顶部菜单中, 而是在视图右上角的UCS图标…

微服务网关(十二)redis流量统计

微服务网关&#xff08;十二&#xff09;redis流量统计中间件 redis流量统计中间件 redis详细&#xff1a; redis.go: // RedisConfPipline redis连接的设置方法&#xff0c;例如在流量统计中间件中设置数据和超时时间 func RedisConfPipline(pip ...func(c redis.Conn)) e…

Linux 内核定时器实验

目录 一、内核时间管理简介 二、内核定时器简介 三、驱动编写 1、修改makefile 2、添加定义 3、初始化led函数 4、添加调用 5、初始化定时器与定时器处理函数 这部分代码如下 四、ioctl函数 五、内核添加unlocked_ioctl 函数 1、添加设备操作集unlocked_ioctl成员 2…

【Android 后台持续定位】

最近工作中遇到了一个涉及后台持续性定位的问题。这里做一下总结&#xff1a;随着Android版本的条件&#xff0c;Google对后台服务管控的也是越来越严格。 这时有的小伙伴会说了&#xff0c;开启一个service然后把服务和通知关联一下变成前台服务&#xff0c;不就行了&#xff…

steam/csgo搬砖,2023年最暴利的项目

这个项目赚钱主要来源于两个地方&#xff1a; 1.比如说今天美元的汇率是1美元6.8人民币&#xff0c;那我们有特定的渠道能拿到1美元5.0-5.5左右人民币的价格&#xff0c;100美元的汇率差利润就有180元左右的利润&#xff0c;当然这个价格是根据国际的汇率上下会有浮动的。 2.…

什么是极速文件传输,极速文件传输如何进行大文件传输

当谈到大文件传输时&#xff0c;人们总是担心大数据文件的大小以及将它们从一个位置交换到另一个位置需要多长时间。由于数据捕获高分辨率视频和图像的日益复杂&#xff0c;文件的大小不断增加。数据工作流在地理上变得越来越分散。在一个位置生成的文件在其他位置处理或使用。…