文章目录
- 1. 搭建环境
- 2. 运行官方首个程序
- 3. AS中运行
- iOS
- Android
- 语法简述
- 1. 变量常量
- 字符串补充
- 2. 集合
- 3. 函数
- 关于可选报错:
- 匿名函数
- 4. 特殊运算符
- 5. 类
- dart 包
1. 搭建环境
环境的搭建在window和mac都差不多,都是从官网下载对应操作系统对应版本的SDK;
然后就是配置flutter下的bin到对应系统的环境变量,我这里是mac使用的zsh,配置.zshrc 或者.zsh_profile等文件我的配置如下:
flutter 配置
export PUB_HOSTED_URL="https://pub.flutter-io.cn"
export FLUTTER_STORAGE_BASE_URL="https://storage.flutter-io.cn"
export FLUTTER_HOME=$HOME/dev/flutter
export PATH="$PATH:$FLUTTER_HOME/bin"
export PATH="$PATH:$FLUTTER_HOME/bin/cache/dart-sdk/bin"
2. 运行官方首个程序
flutter安装完毕后,创建一个工作目录,用来存放flutter项目;然后再当前目录执行 :
flutter create hello_flutter
关于包名,要求如下:
- 包名应该全部小写
just_like_this
, - 用下划线分隔单词
- 仅使用基本拉丁字母和阿拉伯数字:[a-z0-9_]
- 确保该名称是有效的 Dart 标识符——它不以数字开头,也不是保留字。
如果出现大写就会出现下列错误:
"Hello_word" is not a valid Dart package name.The name should be all lowercase, with underscores to separate words,
"just_like_this".Use only basic Latin letters and Arabic digits: [a-z0-9_].Also,
make sure the name is a valid Dart identifier—that it doesn't start with digits
and isn't a reserved word.
See https://dart.dev/tools/pub/pubspec#name for more information.
Try "hello_word" instead.
其他注意事项见:https://dart.dev/tools/pub/pubspec#name
3. AS中运行
打开AS 选择打开已经存在的项目,选择文件,然后就可以在AS种编译了;
iOS
在AS中启动iOS模拟器要是启动设备,检查下默认xcode,因为我有多个xocde默认没有选择不是系统的所以云信iOS模拟器失败;AS中默认启动的是application下的xcode模拟器;可以使用命令:
xcode-select -psudo xcode-select --s /Applications/Xcode.app/Contents/Developer
Android
Android studio运行官方demo出现以下错误:
Exception in thread “main” java.util.zip.ZipException: zip END header not found
...
通过在其官方的issue中找到错误原因:这个错误与 Gradle 有关,这个错误通常是由于 Gradle 设置损坏或不完整所导致的,解决步骤如下:
- 转到用户根目录并找到隐藏.gradle文件夹并将其删除。
如果您使用的是 Mac,请打开终端并执行
cd ~
rm -rf .gradle
- 然后运行你的应用程序到 Android 模拟器或设备(Physical device),不要取消,并确保有稳定的互联网连接(国内可能需要…),在这时候AS将自动下载新的 Gradle;
- 下载完成后,项目运行成功;如图:
语法简述
1. 变量常量
在Dart中支持显示声明和类型推导,如下:
// 显示声明String name = "Aman";// 类型推导var age = 20;// 可修改name = "Aman1";age = 21;print("name is ${name},age is ${age}");
- 常量
有两种声明方式 final 和 const
/ finalfinal String add = "test";// add = "test1"; //不可修改// constconst String add1 = "test2";// add1 = "test3"; // 不可修改
这两个的区别是,const 必须赋值常量值,是要在编译期间确定的值;final可以是运行期间确定的值;如下:
// final var timer = DateTime.now().millisecondsSinceEpoch;//推导类型不能用于 const和 finalfinal int timer = DateTime.now().millisecondsSinceEpoch;// const int timer1 = DateTime.now().millisecondsSinceEpoch;//const 必须是常量值const int timer2 = 3333;
在日常开发中常用final;例如:
class Person {String name;int age;Person(this.name, this.age);
}
final p = Person("Aman", 20);
final p1 = Person("Andy", 38);//这里2.0之前需要使用 const Person("Andy", 38)
print(identical(p, p1));
// false
其中identical使用与判断两个对象是否相等;
上面的实例也介绍其中的dart的类定义;
const示例:
const p_c = Person("LiSi",50); //这样报错:The constructor being called isn't a const constructor.const p_c1 = Person("VeLi", 58);print("const 比较:${identical(p_c, p_c1)}");// false
类需要修改:
class Person {final name;final age;const Person(this.name, this.age);
}
也就是要把构造器改成const的;通过上面的输出也能知道这样 写并不是单例;
需要注意的是dart中没有非空即真
,也就是判断一个对象是否存在,需要明确的bool类型;例如:
String name = "Aman";if (name) {}
会报错:Conditions must have a static type of 'bool'.
字符串补充
dart支持类似Python的多行字符串定义:
var str = """这里都是字符串""";print(str);
2. 集合
和大多数语言类似。这里直接看示例:
void main(List<String> args) {// 集合 list [] 字面量创建var name = ['a', 'b', 'c'];for (var item in name) {print(item);}// set {}字面量创建var set = {1, 2, 3, 4, 5};for (var element in set) {print(element);}// mapvar map = {'name': 'zhangsan','age': 18,'sex': '男',};for (var key in map.keys) {print(key);}
}
3. 函数
dart中不支持函数重载,参数有可选参数(位置可选参数和命名可选参数)和必传参数:
// 必传参数
testString(String name) {print(name);
}// 位置可选参数
testopt(String name, [int age = 0, double weight = 0.0]) {print(name);
}// 命名可选参数
TestsOpt1(String name, {int age = 0, double weight = 0.0}) {print(name);
}
调用:
testString("dddd");testopt("ddd", 4, 6.0);TestsOpt1("444", age: 1, weight: 9);
关于可选报错:
The parameter 'num' can't have a value of 'null' because of its type 'int', but the implicit default value is 'null'.
Try adding either an explicit non-'null' default value or the 'required' modifier.
修改成这样:
int add(int a, int b, {String name = "", int num = 0}) {return a + b;
}
匿名函数
function是dart保留词,其使用如下:
testFun(Function f) {f("5454");
}
调用:
testFun((test) {print(test);});
注意Function是无参数的,在实例中是可以使用传参的所以一般使用如下:
typedef TestFunP = void Function(String name);
testFun1(TestFunP f) {f("5454");
}
4. 特殊运算符
dart中大部分的运算符和其他语言类似;
??=
使用如下:
// 赋值运算符 当原来的变量不是空的时候才会赋值var name = "10";name ??= "123";print(name);
- 级联运算符 …
class Person {var name;var age;Person(this.name, this.age);run() {print("run:${this.name} ${this.age}");}eat() {print("eat:${this.name} ${this.age}");}
}var per = Person("ddd", 1)..name..run()..eat();
相当于类中函数的链式调用;
5. 类
语法和c++类似,有默认构造函数,如果有自定义构造函数那么就会覆盖默认构造函数;自定义构造函数与其他语言不同的是。类似上面实例的调用:
Person(this.name, this.age);
这种事dart的一种语法糖;
- 由于Dart不支持函数重载;类似不同参数的构造实现可以使用**
命名构造函数
**;
// 命名构造函数Person.withNameAgeWeight(this.name, this.age, this.weight);Person.fromMap(Map<String, dynamic> map) {this.name = map["name"];this.age = map["age"];this.weight = map["weight"];}
- 类的初始化列表
Person(this.name, {int age = 10}) : this.age = age ?? 10;
dart 包
上面使用的方法都是在dart/core
中所以不用导入可以使用,其他库比如math库的导入方法如下:
import 'dart:math' show max, sqrt;//show 只引入库里面的某个方法, hide 不导入某个方法导入其他方法
一般情况下.dart就是一个包或者叫库;
第三方库的使用是通过yaml文件实现;
也就是新建pubspec.yaml
中引入,具体格式见官方;
常用格式如下:
environment:sdk: ">=2.12.0 <3.0.0"flutter: ">=1.17.0"name: flutter_app
description: A new Flutter project.
dependencies:flutter:sdk: flutterhttp: ^1.2.1
-
然后到yaml所在的目录执行 dart pub get 就会下载所有的这个库的依赖和这个库如图:
* -
dart pub get
这个命令执行完毕后会根据pubspec.yaml
中配置的内容下载对应的包,并放置在系统缓存中(包括其依赖的所有包);
在Mac或者Linux系统中,这个缓存目录的地址是:~/.pub-cache
,在windows中这个目录地址是:%LOCALAPPDATA%\Pub\Cache
;也可以通过设置PUB_CACHE更改缓存地址;
- 当下载完依赖包之后,dart会在 .dart_tool/目录中创建一个 package_config.json文件,用来表示当前项目和系统缓存包的映射关系。
注意在3.0以后的版本使用dart需要如下导入库:
import 'package:http/http.dart' as http;
然后就可以按照官方的实例运行:
import 'dart:convert' as convert;
import 'package:http/http.dart' as http;void main(List<String> args) async {// This example uses the Google Books API to search for books about http.// https://developers.google.com/books/docs/overviewvar url =Uri.https('developers.google.com', '/books/v1/volumes', {'q': '{http}'});// Await the http get response, then decode the json-formatted response.var response = await http.get(url);if (response.statusCode == 200) {var jsonResponse =convert.jsonDecode(response.body) as Map<String, dynamic>;var itemCount = jsonResponse['totalItems'];print('Number of books about http: $itemCount.');} else {print('Request failed with status: ${response.statusCode}.');}
}