之前好像分享过一点儿Dart的基本知识,因为要使用flutter开发,就必须学号Dart,所以,还是在这儿分享一下Dart的一些优雅的特性吧。
??= 运算符
在我们的flutter的组件中,我们经常会使用三目运算符来判断一个对象的状态。其实这个也可以使用??=运算符来完成。
首先举个简单得例子:
// 测试??=运算符
// 为空则为赋值运算符后面的,不为空则为其本身
void main() {
var isNull;
var notNull = '我不为null';
isNull ??= '为空吗?给你一个值';
notNull ??= '为空吗?给你一个值';
print(isNull);
print(notNull);
}
然后我们再看一下flutter中的具体应用:
1:我们首先创建一个loading.dart文件,然后在该文件中创建一个Loading.dart的StatelessWidget组件。
import 'package:flutter/material.dart';
// 加载中的组件
class Loading extends StatelessWidget {
const Loading({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Center(
child: Container(
margin: EdgeInsets.fromLTRB(20, 40, 20, 40),
alignment: Alignment.center,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
width: 50,
height: 50,
child: Image.asset('images/loading.png',
color: Colors.grey, fit: BoxFit.cover),
),
SizedBox(height:20),
Text(
'加载中 ... ... ',
style: TextStyle(color: Colors.black45),
textAlign: TextAlign.center,
)
],
),
),
);
}
}
没有什么,就是一个简单得页面。
2:然后我们再创建一个简单得文本组件,就叫做hello_world.dart。在其中也是创建一个StatelessWidget组件,然后在里面创建一个Text组件即可。
import 'package:flutter/material.dart';
// 需要显示的页面组件
class HelloWorld extends StatelessWidget {
const HelloWorld({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Center(
child: Container(
height: double.infinity,
width: double.infinity,
alignment: Alignment.center,
color: Colors.yellow,
child: Text(
'Hello,Flutter!',
style: TextStyle(color: Colors.white, fontSize: 44),
textAlign: TextAlign.center,
)));
}
}
3:然后我们想实现这样一个效果,就是模拟一下数据请求,(我们在这儿使用延时调用来模拟),延时3000毫秒后再加载我们的页面。
我们可以这样写:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:learn_flutter/pages/hello_world.dart';
import 'package:learn_flutter/pages/loading.dart';
void main() => runApp(MainApp());
class MainApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _MainAppState();
}
}
class _MainAppState extends State<MainApp> {
// 首先创建我们需要加载显示的Widget
//此时,helloWorld为空
HelloWorld helloWorld;
@override
void initState() {
super.initState();
Future.delayed(Duration(milliseconds: 5000), () {
setState(() {
helloWorld = HelloWorld();
});
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('测试??='),
),
// 在这儿我们可以使用三目运算符来判断。
body: helloWorld == null ? Loading() : helloWorld,
),
);
}
}
当然,我们也可以使用我们的??=运算符来代替它。
但是如果要使用我们的??=运算符,那么,我们的两个Widget的类型必须相同。所以我们就得把HelloWorld这个组件声明为和Loading相同类型的组件,也就是我们的父组件Widget。
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:learn_flutter/pages/hello_world.dart';
import 'package:learn_flutter/pages/loading.dart';
void main() => runApp(MainApp());
class MainApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _MainAppState();
}
}
class _MainAppState extends State<MainApp> {
// 首先创建我们需要加载显示的Widget
//此时,helloWorld为空 注意定义为了Widget
Widget helloWorld;
@override
void initState() {
super.initState();
Future.delayed(Duration(milliseconds: 5000), () {
setState(() {
helloWorld = HelloWorld();
});
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('测试??='),
),
// 如果helloWorld为空的话,那么,加在Loading()组件,否则加载它本身。
body: helloWorld ??= Loading(),
),
);
}
}
其实,这种写法我们大家了解即可,因为很多语言没有该运算符,但是却有三目运算符,所以,因人而异吧。你喜欢哪个就用哪个。
常量构造函数
当我们创建对象时,如果希望传入相同值,就返回同一个对象,这个时候,可以使用常量构造函数。
来个例子:
我们就举个老师都会举得例子:
创建一个Person类:
class Person {
String name;
int id;
Person(this.name,this.id);
@override
String toString() {
return 'name : ${this.name} , age : ${this.id}';
}
}
然后就创建两个对象,然后我们希望如果该对象的姓名和id都相同的话,那么返回同一个对象。
直接这样做肯定会返回false
void main () {
Person xiaoming1 = Person('小明',11111111);
Person xiaoming2 = Person('小明',11111111);
print(xiaoming1 == xiaoming2); // false
}
这个时候我们可能就需要写一个equals方法,来判断我们的属性值了,如果属性值相同的话就为一个对象,但是这样做好是好,但是有点麻烦。
这个时候来试一下常量构造函数
如果我们直接在构造函数前面加一个const关键字是不可以的,编辑器会给我们语法提示:
无法为具有非final字段的类定义const构造函数。
尝试将所有字段设置为final,或者从构造函数.da中删除关键字“const”
我们在这时会写出这样的代码:
void main() {
Person xiaoming1 = Person('小明', 11111111);
Person xiaoming2 = Person('小明', 11111111);
print(xiaoming1 == xiaoming2); // false
}
class Person {
final String name;
final int id;
const Person(this.name, this.id);
@override
String toString() {
return 'name : ${this.name} , age : ${this.id}';
}
}
这是,你会发现,我们的构造函数已经使用const关键字声明了,但是相同参数得到的对象也不是相同对象。
这是怎么回事?
因为常量构造函数不能使用new关键字来创建对象。
我们上面没用new关键字,系统会自动帮我们加上new关键字。
那你可能就好奇了,不用new我们用什么呢?
在这儿,使用常量构造函数时,需要使用const关键字来创建对象。
试着给上面的两个对象前面(赋值号右边)都加上const关键字。
void main() {
Person xiaoming1 = const Person('小明', 11111111);
Person xiaoming2 = const Person('小明', 11111111);
print(xiaoming1 == xiaoming2); // true
}
这时,我们的构造函数,就成为了常量构造函数。
然后,再记住一点:
将创建的对象赋值给const修饰的标识符时,创建对象时的const可以省略.
也就意味着你可以这样写:
void main() {
const Person xiaoming1 = Person('小明', 11111111);
const Person xiaoming2 = Person('小明', 11111111);
print(xiaoming1 == xiaoming2); // true
}
OK,总结一下我们的常量构造函数:
- 如果使用常量构造函数,那么这个类的所有字段必需都为final修饰的。
- 在使用常量构造函数时,使用const关键字来创建对象或者使用const变量来接受该对象
不要忘了常量关键字的前提:参数相同。如果传入的参数不想同,那么,不管你使用什么声明,怎么接收对象,都不是同一个对象。
END
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。