Flutter(知识点小结)
学习网址
https://book.flutterchina.club/
运算符
main() {
// 与Java相同的运算符操作int a = 1;
++a;
a++;
var b = 1;
print(a == b);
// false
print(a * b);
// 3
bool real = false;
real ? print('real') : print('not real');
// not real
print(real && a == b);
// false
print(real || a == 3);
// true
print(a != 2);
// true
print(a <= b);
// false
var c = 9;
c += 10;
print("c = $c");
// c = 19
print(1<<2);
// 4============================================// 与Java不太一样的运算符操作
// is 运算符用于判断一个变量是不是某个类型的数据
// is! 则是判断变量不是某个类型的数据
var s = "hello";
print(s is String);
// true
var num = 6;
print(num is! String);
// true// `~/` 才是取整运算符,如果使用 `/` 则是除法运算,不取整
int k = 1;
int j = 2;
print(k / j);
// 0.5
print(k ~/ j);
// 0// `as` 运算符类似于Java中的cast操作,将一个对象强制类型转换
(emp as Person).teach();
// ??=运算符 如果 ??= 运算符前面的变量为null,则赋值,否则不赋值
var param1 = "hello", param2 = null;
param1 ??= "world";
param2 ??= "world";
print("param1 = $param1");
// param1 = hello
print("param2 = $param2");
// param2 = world// ?.运算符
var str1 = "hello world";
var str2 = null;
print(str1?.length);
// 11
print(str2?.length);
// null
print(str2.length);
// 报错
}
Dart 没有
public
protected
private
等关键字,如果某个变量以下划线_
开头,代表这个变量在库中是私有的。Dart之可选命名参数和可选位置参数
// 可选命名参数:在方法参数中,使用"{}"包围的参数属于可选命名参数
void _testName(String name, {int age = 18, String email}) {}// 调用包含可选命名参数的方法时,需要使用 `paramName:value`的形式指定为哪个可选参数赋值
_testName('Name', age: 18);
----// 可选位置参数:在方法参数中,使用"[]"包围的参数属于可选位置参数
void _testLocation(String name, [int age = 20, String email]) {}// 可选位置参数是位置,如果想指定某个位置上的参数值,则必须前面位置的已经有值,即使前面的值存在默认值。
_testLocation('Location', 17, '98');
GlobalKey:用于跨 widget 调用。
文章图片
示例:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: MyHomePage(),
);
}
}class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
@override
_MyHomePageState createState() => _MyHomePageState();
}class _MyHomePageState extends State {
final GlobalKey key = GlobalKey();
@override
Widget build(BuildContext context) {
return Scaffold(
body: SwitcherWidget(
key: key,
),
floatingActionButton: FloatingActionButton(
onPressed: () {
key.currentState.changeState();
},
child: Text('切换'),
),
);
}
}class SwitcherWidget extends StatefulWidget {
SwitcherWidget({Key key}) : super(key: key);
@override
SwitcherWidgetState createState() => SwitcherWidgetState();
}class SwitcherWidgetState extends State {
bool isActive = false;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Switch.adaptive(
value: isActive,
activeColor: Colors.blueAccent,
onChanged: (bool currentStatus) {
isActive = currentStatus;
setState(() {});
}),
),
);
}changeState() {
isActive = !isActive;
setState(() {});
}
}
RaisedButton 的 shape 是抽象的 ShapeBorder 类型。
统一四边颜色和宽度
shape: Border.all(color: Color(0xFF00FFFF),style: BorderStyle.solid,width: 2)
// 四个边分别指定颜色和宽度, 当只给bottom时与UnderlineInputBorder一致效果
//shape: Border(top: b, bottom: b, right: b, left: b)
// 底部线
//shape: UnderlineInputBorder( borderSide:BorderSide(color: Color(0xFFFFFFFF), style: BorderStyle.solid, width: 2))
// 矩形边色
//shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10)), side: BorderSide(color: Color(0xFFFFFFFF), style: BorderStyle.solid, width: 2))
// 圆形边色
//shape: CircleBorder(side: BorderSide(color: Color(0xFFFFFF00), style: BorderStyle.solid, width: 2))
// 体育场(竖向椭圆)
//shape: StadiumBorder(side: BorderSide(width: 2, style: BorderStyle.solid, color: Color(0xFF00FFFF))
// 角形(八边角)边色
//shape: BeveledRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(10)), side: BorderSide(color: Color(0xFFFFFFFF), style: BorderStyle.solid, width: 2))
类型检查操作符
as
:类型转换is
:对象是定义类型则返回 true,当对象是定义类型的子类或者实现类时,也返回 trueis!
:对象是定义类型则返回 falseas 操作符可以将对象类型判断和使用两个行为进行合并,如下:
//is 方式
if (emp is Person) {
// Type check
emp.firstName = 'Bob';
}//as 方式,注意当 emp 为 null 或者不是 Person类型时,会抛出异常
(emp as Person).firstName = 'Bob';
赋值操作符
??=
表示当左边变量为 null
时,将右边的值赋给左边变量。b ??= value;
条件操作符
condition ? expr1 : expr2
:满足条件返回 expre1
,否则返回expre2
expr1 ?? expr2:``expre1
不为null
时返回 expre1
,否则返回 expre2
var visibility = isPublic ? 'public' : 'private';
String playerName(String name) => name ?? 'Guest';
级联操作符(..)
使用
..
操作符可以对同一对象执行一系列操作,能够节省中间步骤和临时变量,让代码更高效。其实严格来说,
..
级联语法不是一个操作符。 只是一个 Dart 特殊语法。querySelector('#confirm') // Get an object.
..text = 'Confirm' // Use its members.
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
enum MainAxisAlignment {
start,//将子控件放在主轴的开始位置
end,//将子控件放在主轴的结束位置
center,//将子控件放在主轴的中间位置
spaceBetween,//将主轴空白位置进行均分,排列子元素,首尾没有空隙
spaceAround,//将主轴空白区域均分,使中间各个子控件间距相等,首尾子控件间距为中间子控件间距的一半
spaceEvenly,//将主轴空白区域均分,使各个子控件间距相等
}
final和const的区别:
区别一:final 要求变量只能初始化一次,并不要求赋的值一定是编译时常量,可以是常量也可以不是。而 const 要求在声明时初始化,并且赋值必需为编译时常量。
区别二:final 是惰性初始化,即在运行时第一次使用前才初始化。而 const 是在编译时就确定值了。
类的定义与构造方法
Dart中的类没有访问控制,所以你不需要用
private
, protected
, public
等修饰成员变量或成员函数。class Person {
String name;
int age;
String gender;
Person(this.name, this.age, this.gender);
sayHello() {
print("hello, this is $name, I am $age years old, I am a $gender");
}
}
上面的Person类中有3个成员变量,一个构造方法和一个成员方法,看起来比较奇怪的是Person的构造方法,里面传入的3个参数都是
this.xxx
,而且没有大括号{}
包裹的方法体,这种语法是Dart比较独特而简洁的构造方法声明方式,它等同于下面的代码:Person(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
要调用Person类的成员变量或成员方法,可以用下面的代码:
var p = new Person("zhangsan", 20, "male");
p.sayHello();
// hello, this is zhangsan, I am 20 years old, I am a male
p.age = 50;
p.gender = "female";
p.sayHello();
// hello, this is zhangsan, I am 50 years old, I am a female
Dart中使用extends关键字做类的继承,如果一个类只有命名的构造方法,在继承时需要注意,如下代码:
class Human {
String name;
Human.fromJson(Map data) {
print("Human's fromJson constructor");
}
}class Man extends Human {
Man.fromJson(Map data) : super.fromJson(data) {
print("Man's fromJson constructor");
}
}
由于
Human
类没有默认构造方法,只有一个命名构造方法fromJson
,所以在Man
类继承Human
类时,需要调用父类的fromJson
方法做初始化,而且必须使用Man.fromJson(Map data) : super.fromJson(data)
这种写法,而不是像Java那样将super写到花括号中
。有时候你仅仅只是在某个类的构造方法中,调用这个类的另一个构造方法,你可以这么写:
class Point {
num x, y;
Point(this.x, this.y);
// 命名构造方法调用了默认的构造方法
Point.alongXAxis(num x) : this(x, 0);
}
类的成员方法
一个类的成员方法是一个函数,为这个类提供某些行为。上面的代码中已经有了一些类的成员方法的定义,这些定义方式跟Java很类似,你可以为某个类的成员变量提供getter/setter方法,如下代码:
class Rectangle {
num left, top, width, height;
// 构造方法传入left, top, width, height几个参数
Rectangle(this.left, this.top, this.width, this.height);
// right, bottom两个成员变量提供getter/setter方法
num get right => left + width;
set right(num value) => left = value - width;
num get bottom => top + height;
set bottom(num value) => top = value - height;
}
抽象类和抽象方法
使用abstract修饰一个类,则这个类是抽象类,抽象类中可以有抽象方法和非抽象方法,抽象方法没有方法体,需要子类去实现,如下代码:
abstract class Doer {
// 抽象方法,没有方法体,需要子类去实现
void doSomething();
// 普通的方法
void greet() {
print("hello world!");
}
}class EffectiveDoer extends Doer {
// 实现了父类的抽象方法
void doSomething() {
print("I'm doing something...");
}
}
运算符重载
Dart中有类似于C++中的运算符重载语法,比如下面的代码定义了一个向量类,重载了向量的
+
-
运算:class Vector {
num x, y;
Vector(this.x, this.y);
Vector operator +(Vector v) => new Vector(x + v.x, y + v.y);
Vector operator -(Vector v) => new Vector(x - v.x, y - v.y);
printVec() {
print("x: $x, y: $y");
}
}main() {
Vector v1 = new Vector(1, 2);
Vector v2 = new Vector(3, 4);
(v1 - v2).printVec();
// -2, -2
(v1 + v2).printVec();
// 4, 6
}
枚举类
使用enum关键字定义一个枚举类,这个语法跟Java类似,如下代码:
enum Color { red, green, blue }
mixins
mixins是一个重复使用类中代码的方式,比如下面的代码:
class A {
a() {
print("A's a()");
}
}class B {
b() {
print("B's b()");
}
}// 使用with关键字,表示类C是由类A和类B混合而构成
class C = A with B;
main() {
C c = new C();
c.a();
// A's a()
c.b();
// B's b()
}
静态成员变量和静态成员方法
// 类的静态成员变量和静态成员方法
class Cons {
static const name = "zhangsan";
static sayHello() {
print("hello, this is ${Cons.name}");
}
}main() {
Cons.sayHello();
// hello, this is zhangsan
print(Cons.name);
// zhangsan
}
静态成员变量和静态成员方法
// 类的静态成员变量和静态成员方法
class Cons {
static const name = "zhangsan";
static sayHello() {
print("hello, this is ${Cons.name}");
}
}main() {
Cons.sayHello();
// hello, this is zhangsan
print(Cons.name);
// zhangsan
}
泛型(Generics)
Java和C++语言都有泛型,Dart语言也不例外,使用泛型有很多好处,比如:
正确指定泛型类型会产生更好的生成代码。
泛型可以减小代码的复杂度
Dart内置的数据类型List就是一个泛型数据类型,你可以往List中塞任何你想的数据类型比如整型、字符串、布尔值等
Dart库(Libraries)的导入
Dart目前已经有很多的库提供给开发者,许多功能不需要开发者自己去实现,只需要导入对应的包即可,使用import语句来导入某个包,比如下面的代码:
import 'dart:html';
如果你想导入自己写的某个代码文件,使用相对路径即可,例如当前有一个demo.dart文件,跟该文件同级目录下有个util.dart文件,文件代码如下:
// util.dart文件内容
int add(int a, int b) {
return a + b;
}
在demo.dart文件中如果要引用
util.dart
文件,使用下面的方式导入:// demo.dart
import './util.dart';
main() {
print(add(1, 2));
}
【Flutter(知识点小结)】你可以使用
as
关键字为导入的某个包设置一个前缀,或者说别名,比如下面的代码:import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
// Uses Element from lib1.
Element element1 = Element();
// Uses Element from lib2.
lib2.Element element2 = lib2.Element();
你也可以在导入包时使用
show
/ hide
关键字来导入某个包中的部分功能,比如下面的代码:// 只导入foo
import 'package:lib1/lib1.dart' show foo;
// 导入除了foo的所有其他部分
import 'package:lib2/lib2.dart' hide foo;
导入包时使用
deferred as
可以让这个包懒加载,懒加载的包只会在该包被使用时得到加载,而不是一开始就加载,比如下面的代码:import 'package:greetings/hello.dart' deferred as hello;
异步
Dart提供了类似ES7中的
async
await
等异步操作,这种异步操作在Flutter开发中会经常遇到,比如网络或其他IO操作,文件选择等都需要用到异步的知识。async
和await
往往是成对出现的,如果一个方法中有耗时的操作,你需要将这个方法设置成async
,并给其中的耗时操作加上await
关键字,如果这个方法有返回值,你需要将返回值塞到Future
中并返回,如下代码所示:Future checkVersion() async {
var version = await lookUpVersion();
// Do something with version
}
下面的代码使用Dart从网络获取数据并打印出来:
import 'dart:async';
import 'package:http/http.dart' as http;
Future getNetData() async{
http.Response res = await http.get("http://www.baidu.com");
return res.body;
}main() {
getNetData().then((str) {
print(str);
});
}
参考:
原汁原味的 Dart语言 官网
推荐阅读
- 小学英语必考的10个知识点归纳,复习必备!
- Flutter的ListView
- (六)Component初识组件
- java|java 常用知识点链接
- 心理学知识点总结(1)
- 运用flutter|运用flutter 构建一个发布版(release)APK
- AsyncTask的个人小结
- Flutter自定义view|Flutter自定义view —— 闯关进度条
- 改变从现在开始,行动胜于一切——准初三暑假学习小结(二)
- 高效执行力第六课-小结