一、前言
第一天把Flutter环境搭建了,并简单实现第运行第一个Flutter项目,感觉很不错,一些基本操作和原生体验差不多。用Flutter框架写过App项目的开发者都知道,Flutter是一个使用Dart语言开发的跨平台移动UI框架,通过自建绘制引擎,能高性能、高保真地进行Android和IOS开发。可能很多开发者都会像我一样,会有个疑问?为什么Flutter会选择Dart呢?我特意查了下网上资料,总结以下下面六点:
- Dart在release下是AOT(Ahead Of Time, 运行前,比如普通的静态编译)编译的,编译成快速、可预测的本地代码,使Flutter几乎都可以使用Dart编写,在Debug下,Dart是JIT(jUST In Time 运行时编译,边运行边编译,java虚拟机就用到)编译,开发周期快,就好像Flutter亚热级的热重载。
- Dart可以更轻松地创建以60fps运行的流畅动画和转场,60fps是一个什么概念呢?我相信王者荣耀大家都知道,王者荣耀的游戏时帧率评测报告是在40fps-50fps中,越高的fps会提供更快速的操控流畅度,体验感更舒适。
- Dart可以在没有锁的情况下进行对象分配和垃圾回收。像JavaScript一样,Dart避免了抢占式调度和共享内存,大多数支持并发执行线程的计算机语言(Java、Kotlin、Swift)都使用抢占式来切换线程,抢占就会产生竞态条件,竞态条件很有可能导致严重错误,如应用程序崩溃导致数据丢失等等,一般解决竞态条件使用锁来保护,但是锁本身可能导致卡顿,也有可能产生死锁,而Dart针对这个问题,采取了isolate方法来解决,Dart中的线程称为isolate,不共享内存。那么Dart是单线程的,意味根本不允许抢占。单线程有助于开发者确保关键功能(动画和转场)完成而无需抢占。 Flutter应用程序被编译为本地代码,因此它们不需要再领域之间建立缓慢的桥梁,所以启动速度快得多。
- Dart使Flutter不需要单独的声明式布局语言,如JSX或XML,或者单独的可视化界面构建器。其实针对这点我觉得Android的XML界面构建器是很直观阅读的。
- Dart容易学习,具有静态和动态语言用户都熟悉的特性。
- 易于移植,Dart可编译成ARM和X86代码,这样Dart移动应用程序可以在IOS、Android和其他地方运行。
那知道Flutter为什么选择Dart之后,作为开发Flutter项目来讲,把Dar学好就很有必要了,下面就从基本语法开始对Dart入门。
二、Dart环境
1.本地环境
我这边本地是用IntelliJ IDEA 来编写Dart项目,我这边简单说一下环境配置流程:
- 下载Flutter sdk 之前下载过,在第一天配置Android Stdio环境有说。
- Dart插件的安装,Windows下选择
File –Setting –Plugins 搜索Dart下载,而Mac下选择屏幕左上角IntelliJ IDEA –Perferences –Plugins ,如下图:
下载完重启即可。
- 配置
Dart SDK 位置,Windows下选择File –Setting –Languages & Frameworks –Dart –Dart SDK Path 配置,而Mac下选择屏幕左上角IntelliJ IDEA –Perferences –Languages & Frameworks ,如下图:
4.在File –New –Project –Dart ,选择Dart 语言,如下图:
- 创建项目名字,设置项目路径,如下图:
6. 最后点击Finish 按钮,会看到项目已经被创建了,如下图:
2.网页环境
除了上面通过IntelliJ IDEA 本地配置环境外,如果觉得上面配置Dart环境太麻烦就走网页环境,就是下面这个链接直接在线编写Dart小语法练习项目https://dartpad.dartlang.org/,下面例子是循环输出5个hello,示意图如下:
看还是很方便快捷的注意:可能需要 F-Q 才能运行出结果.
三、Dart一些概念
- 在Dart中,一切都是对象,所有的对象都是继承
Object ,也就是所有能够使用变量引用的都是对象,每个对象都是一个了类的实例。在Dart中甚至数字、方法和null都是对象。
- 没有赋初值的变量都会有默认值
null
- 标识符可以以字母或者
_ 下划线开头,后面可以是其他字符和数字的组合。
- Dart支持顶级方法,如
main 方法,同时还支持在类中定义函数(静态函数和实例函数),还可以在方法中定义方法,Dart支持顶层变量,也支持类变量或对象变量。
- Dart没有
public 、protected 、private 关键字。如果某个变量以下划线_ 开头,代表这个变量是在库中是私有的。
- Dart中的类和接口都是统一的,类即是接口,你可以继承一个雷,也可以实现一个类,自然也包含了良好的面向对象和并发编程的支持。
-
final 的值只能被设定一次。const 是一个编译时的常量,可以通过const 来创建常量值,var n = const[] ,这里n还是一个变量,只是被赋值了一个常量值,它还是可以符其他值。实例变量可以是final,但不能是const。
- Dart是强类型语言,但可以用
var 或者dynamic 来声明一个变量,Dart会自动推断其数据类型,dynamic 类似C#
- 使用静态类型可以更清晰表面你的意图,并且可以让静态分析工具来分析你的代码。
- Dart在运行之前会先解析你的代码。你可以通过使用类型或者编译时常量来帮助Dart去捕获异常以及让代码运行的更高效。
- Dart工具可以指出两种问题:警告和错误。警告只是说你的代码可能有问题,但是并不会阻止你的代码执行。错误可以是编译时错误也可以是运行时错误。遇到编译时错时,代码将无法执行;运行时错误将会在运行代码的时候导致一个异常。
四、Dart语法
1.关键字
下表是Dart语言的关键字
const |
null |
class |
new |
this |
as |
default |
final |
continue |
throw |
assert |
deferred |
finally |
operator |
true |
async |
do |
for |
part |
try |
async* |
dynamic |
get |
rethrow |
typedef |
await |
else |
if |
return |
var |
break |
enum |
implements |
set |
void |
case |
export |
import |
static |
while |
catch |
external |
in |
super |
with |
false |
extends |
is |
switch |
yield |
abstract |
factory |
library |
sync* |
yield* |
2.一个最基本的Dart程序
printNumber(num Number){
print('The number is $Number');
}
void main(){
var number = 6.76;
printNumber(number);
}
上面是一个简单基本的Dart 程序,虽然简单但是用到了Dart 很多特性:
-
// 这是注释符号,还可以用/*...*/ 这是很多语言的注释符号
-
num 这是数值型,String ,int ,bool 是另外其他几种类型。注意:数值型num 包含整形int 和浮点型double 。
- 6.76是一个数字常量,数字常量是编译时常量。
-
print() 打印内容的方法
-
"..." 或者是'...' 表示字符串常量
-
$variableName 或者是${expression} 是字符串插值:在字符串常量中引用变量或者表达式
-
var 一种不指定类型声明变量的方式
-
main() 是Dart程序的入口方法,每个程序都需要一个这样得分方法
3.Variables变量
var name = 'knight';
上面是声明变量并赋值的示例,变量是一个引用,上面的名字为name 的变量引用一个内容为"knight" 的String对象。
4.Default value(默认值)
没有初始化的变量自动获取一个默认值为null 。类型为数字的变量如果没有初始化那么默认的值也是null ,因为数字类型也是对象,上面直接上代码:
printNumber(num Number){
print("The number is $Number");
}
void main(){
var number;
printNumber(number);
}
上面打印的结果是The number is null 。
5.Optional types(可选的类型)
声明变量的时候,可以选择加上具体类型,如下面:
double number = 6.666;
添加类型可以更加清晰表达你的意图。IDE编译器等工具有可以使用类型来更好的帮助,提供提示代码补全,提前发现bug等功能。
6.Final and const
如果以后不打算修改一个变量,使用final 或者const 。一个final 变量只能赋值一次;一个const 变量是编译时常量。注意:const 变量同时也是final 变量,实例变量可以为final 但不能是const 。直接上例子:
final double number = 6.666;
number = 6.667;
printNumber(number);
上面例子用final 修饰number 并赋值,但number = 6.67 的时候,想重新给number 再赋值的时候,编译错报错:number,a final variable,can only be set once. ,意思和上面所说的一样就是final 变量只能赋值一次!下面改为定义为const 来修饰number :
const double number = 6.666;
number = 6.667;
printNumber(number);
同样number = 6.667 编译器会报错Constant variables can not be assigned a value 意思是常量值不能赋值,上面也说了,因为const 变量同时也是final 变量。如果const 变量在类中,请定义为static const 。可以直接定义const 和旗初始值,也可以定义一个const 变量使用其他const 变量的值来初始化其值,如下面:
const double number = 6.66;
const double number1 = 2 * number;
上面例子的number1 就是用了number 来将自己初始化值,const 关键字不仅仅只用来定义常量。有可以用来创建不变的值,还能定义构造函数为const 类型
,这中类型的构造函数创建的对象是不可改变的,任何变量都可以有一个不变的值。
7.Built-in types(内置的类型)
在Dart有几种内置的数据类型:数值型-Number、布尔型-boolean、键值对-Map、字符串-String、列表-List、其他类型-Runes、Symbols
7.1数值型-Number
Dart中提供了两种类型:
void main(){
num x = 777;
x = 777.7;
int y = 777;
y = 777.7;
double n = 77,7;
d = 77;
int x1 = 7;
int x2 = 77;
int x3 = 777;
int x4 = 7777;
print('${x1.bitLength}');
print('${x2.bitLength}');
print('${x3.bitLength}');
print('${x4.bitLength}');
}
上面例子可以看到三个点:
- 使用
num 声明的变量,可以随意的转换类型,如果使用int 或者double 明确的声明,那就不能转换了
- 判断一个
int 值需要多少位时,可以使用bitLength
8.数值型的操作
运算符:+、-、*、/、~/、%
常用属性:isNaN、isEven、isOdd
常用方法:abs()、round()、floor()、ceil()、toInt()、toDouble()
void main(){
int i =7;
double d = 10.1;
print(i / d);
print(i ~/ d);
print(i.isOdd);
print(i.isEven);
var x1 = int.parse("7");
print(x1 == 7);
var x2 = double.parse("7.7");
print(x2 == 7.7);
var x3 = 7.toString();
print(x3 == '7');
var x4 = 7.1234.toStringAsFixed(2);
print(x4 == '7.12');
var x5 = (-7).abs();
print(x5 == 7);
var x6 = (7.7).round();
print(x6);
var x7 = (7.3).round();
print(x7);
var x8 = (7.7).floor();
print(x8);
var x9 = (7.7).ceil();
print(x9);
double num1 = 7.77;
print(num1);
double num2 = 7;
print(num2);
int num3 = 7;
print(num3.toDouble());
double num4 = 7.77;
print(num4.toInt());
}
上面列出了一些平时遇到最多的操作,如求余,求整,类型转换等。
9.Strings(字符串)
Dart字符串是UTF-16编码的字符序列,可以使用单引号或者双引号来创建字符串:
void main(){
String m_str1 = '单引号字符串';
String m_str2 = "双引号字符串";
print(m_str1);
print(m_str2);
}
String中单、双引号互相嵌套情况
void main(){
String m_str1 = '单引号中的"双引号"字符串';
String m_str2 = "双引号中的'单引号'字符串";
print(m_str1);
print(m_str2);
String m_str3 = '单引号中的\'单引号\'';
String m_str4 = "双引号里面有双引号,\"双引号\"";
print(m_str3);
print(m_str4);
}
单引号嵌套单引号之间不允许出现空串(不是空格),双引号嵌套双引号之间不允许出现空串:
String m_str6 = '单引号'' ''单引号';
print(m_str6);
String m_str7 = '单引号''*''单引号';
print(m_str7);
String m_str9 = "双引号"" ""双引号";
print(m_str9);
String m_str10 = "双引号""*""双引号";
print(m_str10);
单双引号混合嵌套空串是可以的,如下:
String m_str11 = '单引号""""单引号';
print(m_str11);
String m_str12 = '单引号"" ""单引号';
print(m_str12);
String m_str13 = '单引号""*"""单引号';
print(m_str13);
String m_str14 = "双引号''''双引号";
print(m_str14);
String m_str15 = "双引号'' ''双引号";
print(m_str15);
String m_str16 = "双引号''*''双引号";
print(m_str16);
字符串拼接方式,如下:
String m_str1 = '单引号字符串' '拼接' '---';
print(m_str1);
String m_str2 = '单引号字符串'
'换行''加空格' '';
print(m_str2);
String m_str3 = "单双引号字符串加空格" '拼接' "----";
print(m_str3);
String m_str4 = "单双引号字符串"
'换行' '加空格' '***';
print(m_str4);
String m_str5 = '''
三个单引号+
拼接
''';
print(m_str5);
String m_str6 = """
三个双引号+
拼接
""";
print(m_str6);
String m_str7 = "正常拼接"+",用加号了来拼接";
print(m_str7);
通过提供一个r 前缀可以创建"原始raw"字符串,在字符串加字符,或者在\ 前面再加一个\ ,可以避免\ 的转义作用,如下:
String m_str1 = r"sdsdsds";
print(m_str1);
print("换行:\n");
print(r"换行:\n");
print("换行:\\n");
${表达式的使用} ,类似JS中ES6的表达式使用,使用$ 可以获取字符串的内容,用${表达式} 可以将表达式的值放入字符串中,使用${表达式} 也可以使用字符串拼接。下面也是直接上例子:
bool flag = true;
String m_str1 = "字符串";
print("看看这个值:${m_str1} ""看看这个值flag:${flag}");
String name = "knight";
print("$name" + "CTO");
String m_str = "Android";
assert('${m_str.toUpperCase()} is very good' ==
'ANDROID is very good');
==操作符判断两个对象的内容是否一样,如果了;两个字符串包含一样的字符编码序列,则他们是相等的。在生产模式 assert() 语句被忽略了。在检查模式assert(condition) 会执行,如果条件不为 true 则会抛出一个异常。
10.Boolean(布尔值)
Dart中以bool 代表布尔值,只有两个对象是布尔类型的,那就是true 和false 所创建的对象,这两个对象都是编译时常量。当Dart需要一个布尔值,只有true 对象才被认为是true,所有其他值都是false。看下下面的例子:
String name ="knight";
if(name){
print(name);
}
上面代码会抛出异常,提示name 不是布尔值,Dart使用的是先式的检查值,如下图:
var fullName = '';
assert(fullName.isEmpty);
var hitPoints = 0;
assert(hitPoints <= 0);
var unicorn;
assert(unicorn == null);
var iMeantToDoThis = 0 / 0;
assert(iMeantToDoThis.isNaN);
assert 是语言内置的断言的函数,仅在检查模式有效,在开发过程中,除非条件为真,否则会引发异常。(断言失败则程序立刻终止)
11.Lists列表
array 是编程语言中最常见的集合类型,我相信身为开发者,都用过。在Dart 中数组就是List 对象,所以一般称为lists ,下面直接上Dart list的示例:
List list = [0,1,2,3,4];
List list1 = new List();
List list2 = const[0,1,2,3];
List list3 = new List<String>();
List list4 = new List(5);
List list5 = new List.from([0,1,2,3]);
List list6 = new List()..length = 10;
List list7 = new List.unmodifiable([0,1,2]);
List list8 = new List<int>.generate(5, (int i){
return i + i;
});
List常用的一些api:
List list = [1,2,3,false,"Kinght"];
print(list);
list.add(7);
print(list);
list[1] = "paul";
print(list);
list.remove("paul");
print(list);
list.removeAt(0);
print(list);
print(list.length);
list.insert(0, "Android");
print(list);
print(list.indexOf("Android"));
List list1 = [3,1,2,6,7];
list1.sort((a,b) => a.compareTo(b));
print(list1);
简单总结:
- 下标索引从0开始。
- 可以直接打印List的元素,List也是一个对象。
12.Maps
通常来讲,Map是一个键值对相关的对象,键和值可以是任何类型的对象。每个键只出现一次,而一个值则可以出现多次。上面直接上Map集合的创建方式:
Map map1 = new Map();
map1["one"] = 'Android';
map1["two"] = 'IOS';
map1["three"] = 'Flutter';
print(map1);
Map map2 = Map.of(map1);
print(map2);
|
请发表评论