当前位置: 首页 > news >正文

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

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

相关文章:

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

Flutter介绍 纯原生开发主要面临动态化更新和开发成本两个问题&#xff0c;而针对这两个问题&#xff0c;诞生了一些跨平台的动态化框架 跨平台技术简介 Flutter 是 Google 推出并开源的移动应用开发框架&#xff0c;主打跨平台、高保真、高性能。开发者可以通过 Dart 语言开…...

【数据结构】---顺序表的实现

最近学校开始学习数据结构了&#xff0c;没事就手搓一个顺序表。&#x1f308;线性表线性表是n个具有相同特性的数据元素的有限序列&#xff0c;是一种实际中广泛使用的数据结构&#xff0c;常见的线性表有顺序表、链表、栈、队列、字符串。线性表在逻辑上是线性结构&#xff0…...

JavaScript刷LeetCode拿offer-经典高频40题vaScript刷LeetCode拿offer-经典高频40题

工作太忙没有时间刷算法题&#xff0c;面试的时候好心虚。这里双手奉上40道LeetCode上经典面试算法题&#xff0c;整理的内容有点长&#xff0c;建议先收藏&#xff0c;慢慢消化&#xff0c;在来年顺利拿到满意的offer。 1、[LeetCode] 两数之和 给定一个整数数组和一个目标值…...

动态规划,这将是你见过最详细的讲解

文章目录一、为什么要讲动态规划呢&#xff1f;二、什么是动态规划三、感受一下递归算法、备忘录算法、动态规划递归算法带备忘录的递归解法&#xff08;自定向下&#xff09;自底向上的动态规划四、动态规划的解题套路1. 穷举分析2. 确定边界3. 确定最优子结构4. 写出状态转移…...

【服务器数据恢复】FreeNAS层UFS2文件系统数据恢复案例

服务器数据恢复环境&#xff1a; Dell存储服务器&#xff0c;采用esxi虚拟化系统&#xff0c;esxi虚拟化系统里有3台虚拟机&#xff1b;上层iSCSI使用FreeNAS构建&#xff0c;通过iSCSI方式实现FCSAN功能&#xff1b;FreeNAS层采用UFS2文件系统。 esxi虚拟化系统里有3台虚拟机中…...

Zookeeper安装和基本使用

目录标题一、下载二、安装三、启动客户端测试四、使用zk一、下载 注意&#xff1a;自zk3.5.5版本以后&#xff0c;已编译的jar包&#xff0c;尾部有bin&#xff0c;应该使用的是apache-zookeeper-3.8.0-bin.tar.gz。&#xff0c;因此在下载高版本时&#xff0c;因该下载后缀带b…...

字节面试惨败,闭关修炼再战美团(Android 面经~)

作者&#xff1a;王旭 前言 本人从事Android 开发已经有5年了&#xff0c;受末日寒气影响&#xff0c;被迫在家休整&#xff0c;事后第一家选择字节跳动面试&#xff0c;无奈的被面试官虐得“体无完肤”&#xff0c;好在自己并未气馁&#xff0c;于是回家开始回家进行闭关修炼…...

【机器学习实战】七、梯度下降

梯度下降 一、线性回归 线性回归算法推导过程可以基于最小二乘法直接求解&#xff0c;但这并不是机器学习的思想&#xff0c;由此引入了梯度下降方法。本文讲解其中每一步流程与实验对比分析。 1.初始化 import numpy as np import os %matplotlib inline import matplotli…...

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

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

Spring Boot 日志

目录 1.概述 2.切换日志实现 3.使用 3.1.日志级别 3.3.日志离线 3.4.详细定制 1.概述 由一些历史原因&#xff0c;JAVA领域存在有很多日志框架&#xff0c;如Log4j、Logback、log4j2。 log4j是Java日志框架的元老&#xff0c;在log4j被Apache Foundation收入门下之后&a…...

好用的研发管理看板工具有哪些?10款主流看板管理软件盘点

10大企业看板工具软件&#xff1a;1.软件开发项目看板 PingCode&#xff1b;2.通用看板软件 Worktile&#xff1b;3.开源看板软件 Wekan&#xff1b;4.免费看板软件 Trello&#xff1b;5.个人和小团队的看板软件 Todoist &#xff1b;6.开源免费看 Kanboard&#xff1b;7.面向个…...

【软考系统架构设计师】2022下案例分析历年真题

【软考系统架构设计师】2022下案例分析历年真题 【软考系统架构设计师】2022下案例分析历年真题【软考系统架构设计师】2022下案例分析历年真题2022下案例分析历年真题第一题&#xff08;25分&#xff09;2022下案例分析历年真题第二题&#xff08;25分&#xff09;2022下案例分…...

Java skill - @JsonAlias 和 @JsonProperty

Java skill - JsonAlias 和 JsonPropertyJava skill系列目录&#xff1a;JsonAlias 和 JsonProperty使用 JsonProperty 的麻烦场景&#xff1a;使用 JsonAlias 应对麻烦场景&#xff1a;Java skill系列目录&#xff1a; 【Java skill - 统计耗时用StopWatch】 【Java skill - …...

【实际开发18】- 静态 3

目录 1. 调试与评估 2. 单元测试的管理 1. 单元测试的文档 3. 系统集成的模式与方法 1. 集成测试前的准备 2. 集成测试的模式 3. 大棒集成方法 ( Big-bang Integration) 4. 自顶向下和自底向上集成方法 1. 自顶向下法 ( Top-down Integration ) 2. 自底向上法 ( Bott…...

【swagger2】开发api文档

文章目录一、swagger2 简介背景Open API ???swagger2的作用swagger2常用工具组件&#xff1a;二、Springfox三、springBoot使用swagger2&#xff08;简单示例&#xff09;四、Swagger-UI使用五、配置文件1、配置类&#xff1a;给docket上下文配置api描述信息2、配置类&#…...

Github 上如何提交 pull request

什么是复刻&#xff08;forking&#xff09;? 我们可以通过复刻操作将喜爱的仓库保存自己的Github账户中&#xff0c;以便独立地对其进行操作。 通过复刻&#xff0c;我们可以得到包含完整版本历史的目标仓库的实例&#xff0c;之后可以对复刻得到的仓库进行任意操作而不会影响…...

Redis面试知识

概述 Redis 是速度非常快的非关系型(NoSQL)内存键值数据库,可以存储键和五种不同类型的值之间的映射。 键的类型只能为字符串,值支持五种数据类型:字符串、列表、集合、散列表、有序集合。 Redis 支持很多特性,例如将内存中的数据持久化到硬盘中,使用复制来扩展读性能…...

Spring面试重点(四)——Spring事务

Spring事务 事务的方式 spring中使用事务有两种方式&#xff0c;一种是编程式事务&#xff0c;一种是声明式事务。编程式事务推荐使用TransactionTemplate&#xff0c;实现TransactionCallback接口&#xff0c;需要编码实现&#xff1b;声明式事务只需要在函数增加注解Transa…...

♡ — MySQL 存储引擎

MySQL 存储引擎架构 MySQL 存储引擎采用的是插件式架构&#xff0c;支持多种存储引擎&#xff0c;我们甚至可以为不同的数据库设置不同的存储引擎以适应不同场景的需要&#xff1b;存储引擎是基于表的&#xff0c;而不是数据库。 MyISAM 和 InnoDB 的区别 MySQL 5.5 之前&am…...

大数据技术架构(组件)34——Spark:Spark SQL--Optimize

2.2.3、Optimize2.2.3.1、SQL3.3.1.1、RB1、Join选择在Hadoop中&#xff0c;MR使用DistributedCache来实现mapJoin。即将小文件存放到DistributedCache中&#xff0c;然后分发到各个Task上&#xff0c;并加载到内存中&#xff0c;类似于Map结构&#xff0c;然后借助于Mapper的迭…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...

Go 并发编程基础:通道(Channel)的使用

在 Go 中&#xff0c;Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式&#xff0c;用于在多个 Goroutine 之间传递数据&#xff0c;从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测

uniapp 中配置 配置manifest 文档&#xff1a;manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号&#xff1a;4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看

文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...

day36-多路IO复用

一、基本概念 &#xff08;服务器多客户端模型&#xff09; 定义&#xff1a;单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用&#xff1a;应用程序通常需要处理来自多条事件流中的事件&#xff0c;比如我现在用的电脑&#xff0c;需要同时处理键盘鼠标…...