IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Flutter-Dart入门,常用细节 -> 正文阅读

[移动开发]Flutter-Dart入门,常用细节

入门

变量

数据类型

dart1.12加入空安全。
在dart中的一切皆是对象,包括数字、布尔值、函数等,它们和Java一样都继承于Object,所以它们的默认值也就是null。在dart主要有: 布尔类型bool、数字类型num(数字类型又分为int,double,并且两者父类都是num)、字符串类型String、集合类型(List, Set, Map)。

结构:【类型】【变量名】= 【赋值】

/// 变量
void variable(){
  bool isBool = false;
  String name = "flutter";
  int age = 1;
  double height = 12.1;

  //打印类型
  print(isBool.runtimeType); /// bool
  print(name.runtimeType); /// String
  print(age.runtimeType); /// int
  print(height.runtimeType); /// double
}

细节一:num类型的变量,自带了数学函数Math功能,不像其他语言

double height = -12.1;
print("height ${height.abs()}");
/// 输出12.1

集合

new 关键词是可选的,创建对象,不需要显示声明关键字new。

void collection(){
  List<String> colorList = ['red', 'yellow', 'blue', 'green'];
  /// forEach箭头函数遍历
  colorList.forEach((String color) => print(color));

  /// map函数的使用
  print(colorList.map((color) => '1+$color').join(","));
  
  /// 直接使用{}形式初始化
  Set<String> colorSet = {'red', 'yellow', 'blue', 'green'};
  //for-in遍历
  for (var color in colorSet) {
    print(color);
  }
  
  Map<String, int> colorMap = {'white': 0xffffffff, 'black':0xff000000};
  print(colorMap.containsKey('green'));//false
  print(colorMap.containsValue(0xff000000));//true

print(colorMap.runtimeType);
}

打印set和map 显示的是_InternalLinkedHashMap,网上有对这个说明。

空安全null safety

从dart 2.12开始,支持空安全。就是在类型后面加个?

/// 空安全
void nullSafety(){
  /// 默认是null
  String? nullStr;
  int? nullInt;
  bool? nullBool;
  Map<String, int>? nullMap;

  /// 报错,Error: Non-nullable variable 'str' must be assigned before it can be used.
  String str;
  // str = "init";
  print("is $str");

}

如果使用String str 申明变量,但又不初始化,在使用的时候就会报错误。

late延时/惰性初始化

正式使用它之前必须得保证初始化过了,否则会报错

  1. 可能不需要该变量,并且初始化它的成本很高。
  2. 这个变量可能从网络获取。
void main() {
  var awesome = Awesome();
  print('awesome: ${awesome.isAwesome}');

  lateVoid();
}

///
late String description;
void lateVoid() {
  description = 'Flutter!';
  print(description);
}

类型推导var、dynamic、object

前面介绍了dart中常用的变量,还可以使用var、dynamic、object用于定义变量,通过这种方式定义变量不需要指定变量类型。

在这里插入图片描述
补充:从图上可以知道object是类型的基类。

使用var、dynamic、object,可以不用指明变量类型。他们区别是什么:
var,编译时会检测类型,如果类型推断出是string类型,再赋值int,会报错。
dynamic,类型是可变的,先复制string再复制int是可以的,编译时不会揣测数据类型,但是运行时会推断。
Object,类型是可变的,先复制string再复制int是可以的,编译时会检测类型。

void varAndDynamic(){

  /// var定义的类型是不可变的,类型推断出是string类型,再赋值int,会报错
  //var
  var str = "flutter";
  print(str.runtimeType); //String
  print(str); //hello world
  // str = 1;

  //dynamic
  /// 编译时不会揣测数据类型,但是运行时会推断
  dynamic mic = "flutter";//编译时不会揣测数据类型,但是运行时会推断
  print(mic.runtimeType);//String
  print(mic);//hello world
  /// 但是这样的坏处就是会让dart的语法检查失效,所以有可能会造成混乱而不报错,所以不要直接使用dynamic
  mic.foo();
  /// 通过它定义的变量会关闭类型检查,这段代码静态类型检查不会报错,但是运行时会crash,因为mic并没有foo()方法,
  /// 所以建议大家在编程时不要直接使用dynamic
  mic=1;
  print(mic.runtimeType);//int 说明类型是可变的
  print(mic);//1

  //Object
  Object object = "flutter";
  print(object.runtimeType);//String
  print(object);//hello world
  object=1;
  print(object.runtimeType);//int 说明类型是可变的
  print(object);//1
  //object.foo();静态类型检查会运行报错会报错
  object.foo();

}

Final 和 Const

如果你不想更改一个变量,可以使用关键字 final 或者 const 修饰变量。一个 final 变量只可以被赋值一次;一个 const 变量是一个编译时常量(const 变量同时也是 final 的)。

final:其值在初始化后不可改变;
const:只能被设一次值,在声明处赋值,且值必须为编译时常量;用于修饰常量。

/// final和const
void finalAndConst(){

  /// 可以用做静态常量
  const int age = 20;

  /// final不能改变
  final String name = 'Flutter';
  /// 以下不能改变
  // name = "zzb";
  print("name $name");

  final int count = 2 * 2;

  /// final只用来修饰变量,但无法限制变量的实例内部发生改变
  final baz = [1];
  // baz=[1,2,3,4]; //出错 此调用修改了变量的实例 即:[1] 和[1,2,3,4]是不同的对象
  baz[0] = 2; //正常执行,只修改了变量引用对象的成员变量的值
  print(baz);


  /// 对比不同点,打印时间
  final String finalTimeStamp = DateTime.now().toString();
  const String constTimeStamp = DateTime.now().toString();//出错,编译时就要确认内容
  
  print("finalTimeStamp $finalTimeStamp");
}

Assert(断言)

在dart中如果条件表达式结果不满足条件(表达式为false),则可以使用 assert 语句中断代码的执行。特别是在Flutter源码中随处可见都是assert断言的使用。注意: 断言只在检查模式(debug调试)下运行有效,如果在生产模式运行,则断言不会执行。

assert(text != null);//text为null,就会中断后续代码执行
assert(urlString.startsWith('https'));

补充

官方不推荐使用forEach方法进行,建议使用for…in替换。

void collection() {
  List<String> colorList = ['red', 'yellow', 'blue', 'green'];

  /// forEach箭头函数遍历
  colorList.forEach((String color) => print(color));
 }

lint语法检测:给出的提示
foreach与fon-in方法pk forEach方法在回调方法出现的弊端。

函数

Dart是一种真正的面向对象的语言,所以即使是函数也是对象,并且有一个类型Function。

函数声明

返回类型,函数名,入参

bool isNull(int? num) {
  return num == null;
}

如果函数体内只包含一个表达式,你可以使用简写语法:

bool isNull2 (int? num) => num == null;

Dart函数声明如果没有显式声明返回值类型时会默认当做dynamic处理,注意,函数返回值没有类型推断,不建议使用

isNull3(int? num) {
  return num == null;
}

参数

有两种形式的参数:必要参数 和 可选参数。必要参数定义在参数列表前面,可选参数则定义在必要参数后面。可选参数可以是 命名的位置的

/// 必选参数
void upload(String filePath, String fileName, int? fileSize) {
}

/// 命名位置参数
void upload2(String filePath, String fileName, {int? fileSize}) {
}

/// 可选位置参数
void upload3(String filePath, String fileName, [int? fileSize]) {
}

/// 测试以上方法
/// 测试以上方法
void testParam(){
  /// 必选参数
  upload("/user", "name", 0);
  /// 命名位置参数,两种用法
  upload2("/user", "name");
  upload2("/user", "name", fileSize: 10);

  /// 可选位置参数
  upload3("/user", "name");
  upload3("/user", "name", 10);
  
  
}

可选命名参数在Flutter中使用非常多。注意,不能同时使用可选的位置参数和可选的命名参数。
命名位置参数,最大的好处是能知道,传递参数的含义,再配上关键词required,required表示这个参数是必须的。

/// required使用
void upload4({required String filePath, required String fileName, int? fileSize}) {
}
/// required使用
  upload4(filePath: "/user", fileName: "name");
  upload4(filePath: "/user", fileName: "name", fileSize: 10);

对象的 成员 由函数和数据(即 方法 和 实例变量)组成。

默认构造函数

如果你没有声明构造函数,那么 Dart 会自动生成一个无参数的构造函数并且该构造函数会调用其父类的无参数构造方法。

/// 默认构造函数
class Point{
  int x = 0;
  int y = 0;
}
Point point = Point();

有参构造函数和命名式构造函数

需要注意的是:使用了有参构造函数和命名式构造函数,那默认的构造函数就无效了。无法直接使用
Point point = Point();

构造函数:声明一个与类名一样的函数即可声明一个构造函数。
命名式构造函数:可以为一个类声明多个命名式构造函数来表达更明确的意图:

class Point{
  int x = 0;
  int y = 0;
  int? z = 0;

  /// constructor,构造函数
  Point(double x, double y) {
    x = x;
    y = y;
  }

  /// 简化,构造函数
  // Point(this.x, this.y);

  /// 命名式构造函数
  Point.origin(){
    x = 5;
    y = 5;
  }

  /// 常用命名式构造函数,把json的数据转成对象
  Point.fromJson(Map<String, dynamic> json){
    x = json['x'];
    y = json['y'];
  }

  void printPoint(){
    print("x = $x y = $y");
  }

  /// 距离
  int distanceTo(){
    return 0;
  }
}

void testPoint(){
  /// 无法直接使用
  // Point point = Point();

  /// 构造函数
  Point point = Point(2,2);
  point.printPoint();

  /// 命名式构造函数
  Point point2 = Point.origin();
  point2.printPoint();

  /// 命名式构造函数
  Point point3 = Point.fromJson({'x': 1, 'y': 2});
  point3.printPoint();

  /// 可以为空的对象,调用方法前可以使用运算符?. 来判断是否有该方法
  /// 可以避免因为左边表达式为 null 而导致的问题
  Point? point4;
  point4?.printPoint();
}

私有属性、私有方法

  1. Dart和其他面向对象语言不一样,Data中没有 public private protected这些访问修饰符合,但是我们可以使用_把一个属性或者方法定义成私有。

  2. 私有方法必须要抽离在单独文件中,否则不生效。

class PrivateClass{
  /// 私有变量
  int _i = 1;
  int j = 2;

  PrivateClass();

  void printContent() {
    print("打印变量_i = $_i j = $j");
  }

  /// 私有方法,
  void _printContent2(){
    print("打印变量_i = $_i j = $j");
  }
}

PrivateClass privateClass = PrivateClass();
  privateClass.printContent();

  /// 修改公共属性
  privateClass.j = 3;
  privateClass.printContent();

  /// 无法修改私有属性,报错The setter '_i' isn't defined for the type 'PrivateClass'.
  privateClass._i = 3;

  /// 无法使用私有方法,The method '_printContent2' isn't defined for the type 'PrivateClass'.
  privateClass._printContent2();

继承

如果父类没有匿名无参数构造函数,那么子类必须调用父类的其中一个构造函数。

class Person {
  String? firstName;

  Person.fromJson(Map data) {
    print('in Person');
  }

  void eat() {
    print("eat");
  }

  void play(){
    print("play");
  }
}

class Teacher extends Person {
  Teacher.fromJson(Map data) : super.fromJson(data) {
    print('in Teacher');
  }

  /// 重写类成员
  @override
  void eat() {
    /// 调用父类方法
    super.play();
    print("eat fish");
  }
}

/// 测试继承
void testExtends() {
  Teacher teacher = Teacher.fromJson({});
  teacher.eat();
}

输出

in Person
in Teacher
play
eat fish

Mixin

Dart 是不支持多继承的,Mixin 是一种在多重继承中复用某个类中代码的方法模式,“组合”类可以访问mixin类的方法、变量而不必成为其子类。使用 with 关键字来使用 Mixin 模式。
定义一个 Person 类,实现吃饭、说话、走路和写代码功能,同时定义一个 Dog 类,实现吃饭、和走路功能:

/// 定义一个 Person 类,实现吃饭、说话、走路和写代码功能,同时定义一个 Dog 类,实现吃饭、和走路功
class Person {
  say() {
    print('say');
  }
}

mixin Eat {
  eat() {
    print('eat');
  }
}

mixin Walk {
  walk() {
    print('walk');
  }
}

mixin Code {
  code() {
    print('code');
  }
}

class Dog with Eat, Walk{}
class Man extends Person with Eat, Walk, Code{}

/// 测试mixin
void testMixin(){
  Man man = Man();
  man.say();//say
  man.code(); //code
  man.eat();//eat

  Dog dog = Dog();
  dog.eat(); //eat
}

打印结果

say
code
eat
eat

Dart之Mixin详解,Flutter中大量使用了这种方式。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-10-29 13:09:42  更:2021-10-29 13:12:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 1:22:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码