很详细的Dart讲解
Dart 数据类型
数据的操作 跟Java差不多
变量与常量
var ,const,final
var a= 10;
a = “10”
a = true
数值型
var ,num (基类) int,double 子类
字符串
var ,String
String a = "h";
print(a*3) --->hhh
布尔型
var ,bool 定义
bool a = true
列表List(数组)
三种方法定义
var a = ["a",1,true,12.5]; 可以是任意类型
var b = const[1,2,3,4,5];不可变 list
List list = new List();
print(a[1]) == >1
Map
var map = {"first":"hello","1":1,2:"shadow","3":true,true:23}
map.constKey(2) ==>true
dynamic 动态变量类型,类似var
运算符
算数运算符,关系运算符,逻辑运算符,赋值运算符,条件表达式
- , - ,*, / , ~/ , %
3/2 == > 1.5
3 ~/ 2 ===>1
&& , ||
赋值运算符 =,??
var a;
var k = "dart";
var c = "java";
var d = a ?? c;
print(d); ==》java
var g = k ?? c;
print(g); ==>dart
控制语句
if,for,while,break,continue,switch...case;
方法
返回值 方法名 (参数){
方法体
}
String test(var a){
return a;
}
等价
test(var a) =>a
可选参数
//可变参数
printPersion(String name, {int age, String formal}) =>
print("name = $name ,age = $age ,formal = $formal");
//位置固参数
printPersion2(String name, [int age, String formal]) =>
print("name = $name ,age = $age ,formal = $formal");
printPersion("shadow");
printPersion("shadow", age: 18);
printPersion("shadow", formal: "meal");
printPersion("shadow", age: 18, formal: "meal");
printPersion2("ying");
printPersion2("ying", 12);
printPersion2("ying", 12, "male");
默认参数值
printPersion(String name, {int age = 15, String formal}) =>
print("name = $name ,age = $age ,formal = $formal");
方法对象
Dart 中任何方法都是对象,可以赋值给变量 运行,也可以作为另一个方法的参数。。。
printHello() => print("hello shadow");
//方法作为对象赋值给变量aa,然后由aa执行
var aa = printHello();
aa(); ==》hello shadow
匿名方法
(可选参数){方法体}
var name = (str) {
print("hello ---- $str");
};
name("shadow");
闭包
闭包函数 就是在一个函数内部声明的函数,这样就可以调用该函数的内部变量
闭包内的函数可以是正常函数也可以是匿名函数
void main() {
var func = aaa();
func(); -->0
func(); -->1
func(); -->2
func(); -->3
func(); -->4
}
//闭包函数 就是在一个函数内部声明的函数
aaa() {
int count = 0;
/*printCount() {
print(count++);
}
return printCount;*/
return (){
print(count++);
};
}
Dart面向对象编程
类和对象
Dart的类和对象跟Java差不多,结合kotlin
- 使用关键字class声明一个lei
- 使用关键字new 创建一个对象,new可以省略
- 所有对象都继承Object类
- 属性默认会生成getter&setter方法
- 使用final声明的属性只有getter方法
- 属性和方法可以可以 . 访问
- 方法不能被重载
- Dart中可见性以library(库)为单位
- 默认情况下 每一个Dart文件就是一个库
- 使用 _ 表示库的私有性:int _name ;私有属性 class _persion{} 私有类
- 使用import导入库
void main() {
var people = People();
people.name = "shadow";
people.age = 18;
print( people.name);
people.work();
}
class People {
int age;
String name;
String address;
work() => print("name = $name , age = $age 在 $address 工作。。。。");
}
计算属性
计算属性的值是通过计算而来,本身不存储值,计算属性赋值,其实是通过极端转换到其他实例变量
void main() {
var ma = aaa();
print(ma.area);
print(ma.computeArea());
}
class aaa {
num width, height;
num get area => width * height; //计算属性 get方法
set area(value) { //计算属性 set方法
width = value / 10;
return width * height
}
//方法计算 面积
computeArea() => width * height;
}
构造函数
- 如果没有自定义构造方法,则会有个默认的构造方法
- 如果存在自定义构造方法,则默认构造方法无效
因为Dart方法不允许重载,所以Dart想要有多个构造函数,只能用命名构造函数
使用类名.方法的形式实现
class People {
int age;
String name;
String address;
final String weight;
/* People (int age,String name,String address,String weight){
this.age = age;
this.name = name;
this.address = address;
this.weight = weight; //传统方式 不能对final属性赋值
}*/
//Dart蜜糖写法,可以允许对final的属性赋值,在构造方法体执行之前赋值
People(this.age, this.name, this.address, this.weight) {}
//命名构造方法,用以创建多个构造方法
People.withAge(this.age, this.weight) {}
//普通方法
work() => print("name = $name , age = $age 在 $address 工作。。。。");
}
常量构造方法
如果一个类中的变量值只需要赋值一次,则可以把这个类设置为常量构造
常量构造,需要此类中所以的变量都是final,并且构造方法以const修饰
void main() {
const people = const People(18, "shadow", "上海", "50");
print(people.age);
print(people.name);
}
class People {
final int age;
final String name;
final String address;
final String weight;
const People(this.age, this.name, this.address, this.weight);
}
工厂构造方法
- 工厂构造方法类似于设计模式中的工厂模式
- 在构造方法前添加关键字factory实现一个工厂构造方法
- 在工厂构造方法中可返回对象
class Logger {
final String name;
static final Map _map = {}; //私有属性
factory Logger(String name) {
if (_map.containsKey(name)) {
return _map[name];
} else {
final logger = Logger._withName(name);
_map[name] = logger;
return logger;
}
}
Logger._withName(this.name); //私有构造方法
}
初始化列表
- 初始化列表会在构造方法体执行之前执行
- 使用分号分隔初始化表达式
- 初始化列表常用于设置final变量的值
class ListStru {
String name;
int age;
final int weight;
ListStru(Map map): this.name = map["name"], this.weight = map["weight"] {
this.age = map["age"];
}
}
静态成员
- 使用static关键字来实现类级别的变量和函数
- 静态成员不能访问非静态成员 非静态成员可以访问静态成员
- 类中的常量需要使用static const声明
void main() {
StaticNum.currentPage = 10;
StaticNum.aaa();
var num = StaticNum();
num.bbb();
}
class StaticNum {
static int currentPage;
static const int weight = 100;
static aaa() {
currentPage++;
print(currentPage);
}
bbb() {
currentPage--;
print(currentPage);
}
}
对象操作符
- 条件成员访问:?. -->判断对象是否为空,不为空才去执行后面的内容
- 类型转换:as
- 是否指定类型 is,is! --->判断对象是否是指定的类型,返回true,false
- 级联操作:.. --->类似build模式,联级调用
void main() {
var num2;
if (num2 is StaticNum) {
num2?.bbb();
}
num2 = StaticNum();
(num2 as StaticNum)?.bbb();
(num2 as StaticNum)
..age = 10
..name = "shadow"
..bbb();
}
class StaticNum {
int age;
String name;
bbb() {
print("name = $name ,age = $age");
}
}
对象call方法(不建议使用,会让代码复杂化)
在Dart中对象可作为方法使用,方法可作为对象使用
想要对象作为方法使用,需要在类中创建call(方法名)方法,参数值,方法体都没有要求。。
void main() {
CallClass callClass = CallClass();
callClass("shadow", 18); //对象当做方法使用
}
class CallClass {
String name;
int age;
call(name, age) => "name = $name ,age = $age";
}
面向对象扩展 :封装 继承 多态
继承,抽象,接口,mixins,操作符复写
继承
- 使用extend 继承类
- 子类会继承父类的可见属性和方法,不会继承构造方法
- 子类能够复写父类的方法、get 和set方法
- 单继承、 多态性
- 子类的构造方法会默认调用父类的无参构造方法
- 如果父类没有无名无参构造方法,则需要显示调用父类的构造方法
- 在构造方法参数后使用 :显示调用父类的构造方法
构造方法的执行顺序 - 父类的构造方法在子类构造方法体开始执行的位置调用
- 如果有初始化列表,初始化列表必须放在父类构造方法前面调用执行
void main() {
//多态
Person p1 = Student("shadow", 18);
print(p1.name);
print((p1 as Student).age);
print(p1);
}
class Person {
String name;
//构造1
Person(this.name);
//构造2
Person.withName(this.name);
}
class Student extends Person {
int age;
//复写构造
Student(String name, int age): this.age = age, super.withName(name);
//Student(String name) : super(name);
}
抽象类
- 抽象类使用**abstract **表示 ,不能直接被实例化
- 抽象方法不用**abstract **修饰,无实现即可,所以有时候 抽象类可作为接口使用
- 抽象类可以没有抽象方法
- 有抽象方法的类一定得声明为抽象类
void main() {
var aaa = A();
aaa.run();
}
abstract class AbstractClass {
void run(); //抽象方法
}
class A extends AbstractClass {
//实现抽象方法
@override
void run() {
print("hello shadow");
}
}
接口
- 类和接口是统一的,类就是接口
- 每个类都隐式的定义了一个包含所有实例成员的接口
- 如果是服用已有类的实现,使用继承(extends)
- 如果只是使用已有类的外在行为,使用接口(implements)
- Dart中抽象类更像接口,所以根据情况使用
class Person{
String Name;
int age;
run() => print("hello shadow");
}
class InterfaceClass implements Person{
@override
String Name;
@override
int age;
@override
run() {
return "hello world";
}
}
mixins 实现多继承
- Mixins 类似于多继承,是在多类继承中重用的一个类代码的方式
- 作为Mixin的类不能有显示声明构造方法
- 作为Mixin的类只能继承自Object
- 使用关键字with连接一个或者多个mixin
//不能有显示声明,不能继承别的类
class A {
a() => print("A.a...");
}
class B {
a() => print("B.a...");
b() => print("B.b...");
}
class C {
a() => print("C.a...");
b() => print("C.b...");
c() => print("C.c...");
}
class D extends A with B, C {}
void main() {
var d = D();
d.a(); //C.a... 与多继承的顺序有关,如果继承的多个类中有相同的方法,调用最后一个类的方法
}
另外一种mixins的使用方式
abstract class Engine {
void work();
}
class OilEngine implements Engine {
@override
void work() {
print("Work with oil....");
}
}
class ElectricEngine implements Engine {
@override
void work() {
print("Work with Electric....");
}
}
class Tyre {
String name;
void run() {}
}
class Bus = Tyre with OilEngine;
class Car = Tyre with ElectricEngine;
/*
class Car extends Tyre with ElectricEngine{
}*/
abstract class Engine {
void work();
}
class OilEngine implements Engine {
@override
void work() {
print("Work with oil....");
}
}
class ElectricEngine implements Engine {
@override
void work() {
print("Work with Electric....");
}
}
class Tyre {
String name;
void run() {}
}
class Bus = Tyre with OilEngine;
class Car = Tyre with ElectricEngine;
/*
class Car extends Tyre with ElectricEngine{
}*/
操作符 复写
void main() {
var p1 = PersonA(18);
var p2 = PersonA(20);
print(p1 > p2); //---》 false
print(p1["age"]);
print(p1 == p2);
}
class PersonA {
int age;
//构造函数
PersonA(this.age);
//重写操作符
bool operator >(PersonA p) {
return this.age > p.age;
}
int operator [](str) {
if ("age" == str) {
return age;
}
return 0;
}
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is PersonA && runtimeType == other.runtimeType && age == other.age;
@override
int get hashCode => age.hashCode;
}
Dart 枚举
void main() {
var currentSeason = Season.spring;
print(currentSeason.index); // == > 0
switch (currentSeason) {
case Season.spring:
print("1 - 3月");
break;
case Season.summer:
print("1 - 3月");
break;
case Season.autumn:
print("1 - 3月");
break;
case Season.winter:
print("1 - 3月");
break;
}
}
//定义枚举
enum Season { spring, summer, autumn, winter }
泛型
void main() {
var list = List();
list.add("hello");
var util = Utils();
util.put(10);
}
class Utils {
T element;
void put(T element) {
this.element = element;
}
}
dart导入库
在Dart中,库的使用时通过import关键字引入的。
Dart中的库主要有三种:
1、我们自定义的库,就是引用别的类(工具类 实体类等)
import 'lib/xxx.dart';
2、系统内置库
import 'dart:math';
import "dart:math";
main(){
print(min(12,23));
print(max(12,25));
}
网络请求库
import 'dart:io';
import 'dart:convert';
async和await
这两个关键字的使用只需要记住两点:
只有async方法 才能使用 await关键字 调用方法
如果调用别的async方法 必须使用 await关键字
async是让方法变成异步。
await是等待异步方法执行完成。
import 'dart:io';
import 'dart:convert';
void main() async{
var result = await getDataFromZhihuAPI();
print(result);
}
//api接口: http://news-at.zhihu.com/api/3/stories/latest
getDataFromZhihuAPI() async{
//1、创建HttpClient对象
var httpClient = new HttpClient();
//2、创建Uri对象
var uri = new Uri.http('news-at.zhihu.com','/api/3/stories/latest');
//3、发起请求,等待请求
var request = await httpClient.getUrl(uri);
//4、关闭请求,等待响应
var response = await request.close();
//5、解码响应的内容
return await response.transform(utf8.decoder).join();
}
3、Pub包管理系统中的库
https://pub.dev/packages
https://pub.flutter-io.cn/packages
https://pub.dartlang.org/flutter/
1、需要在自己想项目根目录新建一个pubspec.yaml
2、在pubspec.yaml文件 然后配置名称 、描述、依赖等信息
name: xxx
description: A new flutter module project.
dependencies:
http: ^0.12.0+2
date_format: ^1.0.6
3、然后运行 pub get 获取包下载到本地 (termial或者cd 进入该项目目录,打开命令面板)
4、项目中引入库 import 'package:http/http.dart' as http; 看文档使用
import 'dart:convert' as convert;
import 'package:http/http.dart' as http;
main(List arguments) async {
// This example uses the Google Books API to search for books about http.
// https://developers.google.com/books/docs/overview
//var url = "https://www.googleapis.com/books/v1/volumes?q={http}";
var url = "http://news-at.zhihu.com/api/3/stories/latest";
// Await the http get response, then decode the json-formatted responce.
var response = await http.get(url);
if (response.statusCode == 200) {
//返回的json字符串
var jsonResponse = convert.jsonDecode(response.body);
//读取json字符串中的字段
var itemCount = jsonResponse['date'];
print("Number of books about http: $itemCount.");
} else {
print("Request failed with status: ${response.statusCode}.");
}
}
Dart库的重命名 Dart冲突解决 ---- as 关键词
部分导入
如果只需要导入库的一部分,有两种模式:
模式一:只导入需要的部分,使用show关键字,如下例子所示:
import 'package:lib1/lib1.dart' show foo; 只能调用foo方法
模式二:隐藏不需要的部分,使用hide关键字,如下例子所示:
import 'package:lib2/lib2.dart' hide foo; 只有foo方法不能调用
延迟加载
也称为懒加载,可以在需要的时候再进行加载。
懒加载的最大好处是可以减少APP的启动时间。
懒加载使用deferred as关键字来指定,如下例子所示:
import 'package:deferred/hello.dart' deferred as hello;
当需要使用的时候,需要使用loadLibrary()方法来加载:
greet() async {
await hello.loadLibrary();
hello.printGreeting();
}