Dart语法精炼(四)

162 阅读3分钟

该部分内容主要分为四部分, 认真看, 一小时, 带你学完Dart基础语法:

测试工具我选择的是VSCode, 打开空白文件夹开始Dart基础语法的学习吧...

dart_learn的仓库

Dart语法精炼(一)

Dart语法精炼(二)

Dart语法精炼(三)

Dart语法精炼(四)

Dart中文网

16. mixin混入的使用

  • 接口implements 需要将所有的方法都实现一遍, 不管原来的接口类是否实现,
  • mixin 混入: 混入类的方法, 只要实现过的, 我都可以拿过来直接用, 比较方便,
  • mixin 语法: 定义可混入的类的时候, 不用class定义, 需要用mixin定义, 然后通过with 进行混入,
  • 当混入类中的方法 和父类中的方法 以及自己的方法名称相同时 => 优先级: 自己的最高, 混入类的次之, 父类的最低.
void main(List<String> args) {
  final sm = SuperMan();
  sm.running(); // SuperMan running
  sm.flying();  // Flyer flying
  sm.eating();  // Person eating
}

mixin Runner {
  void running() {
    print("Runner running");
  }
}

mixin Flyer {
  void flying() {
    print("Flyer flying");
  }
}

class Person {
  void eating() {
    print("Person eating");
  }

  void running() {
    print("Person running");
  }
}

class SuperMan extends Person with Runner, Flyer {
  void running() {
    print("SuperMan running");
  }
}

17. 类属性和类方法

17.1 static 关键字修饰即可

void main(List<String> arguments) {
  Person.day = '2023';
  print(Person.day);  // 2023

  Person.running();   // static running
}

class Person {
  // 静态属性(类属性)
  static String? day;

  // 静态方法(类方法)
  static void running() {
    print("static running");
  }
}

对比对象属性(成员变量)和对象方法:

void main(List<String> arguments) {
  final p = Person();
  p.name = 'zhangsan';
  print(p.name); // zhangsan

  p.eating();    // zhangsan eating
}

class Person {
  // 成员变量
  String? name;
  // 对象方法
  void eating() {
    print("$name eating");
  }
}

17.2 枚举的定义

// 枚举的定义
enum Colors { red, green, blue }

使用上:

final color = Colors.red;

  switch (color) {
    case Colors.red:
      print("红色");
      break;
    case Colors.green:
      print("绿色");
      break;
    case Colors.blue:
      print("蓝色");
      break;
    default:
  }

  // 2.1 获取枚举定义的所有值 => list
  print(Colors.values);      // [Colors.red, Colors.green, Colors.blue]
  // 2.2 获取枚举值所在枚举中的index
  print(Colors.blue.index);  // 2

18. Dart中库的使用

代码中新建utils 文件夹来演示库的使用:

utils文件夹在项目中结构

18.1 Dart 中默认情况下, 一个Dart 文件就是一个模块(库文件)

18.2 引用系统的库: import 'dart: 库的名字':

import 'dart:math';

void main(List<String> arguments) {
  final num1 = 20;
  final num2 = 21;
  print(min(num1, num2)); // 20; 就会引入系统的计算库import 'dart:math';
}

18.3 自定义的库: import '自定义库的相对路径/库的名字':

// math_utils.dart
int sum(int num1, int num2) {
  return num1 + num2;
}
import 'dart:math';
import 'utils/math_utils.dart';

void main(List<String> arguments) {
  final num1 = 20;
  final num2 = 21;
  print(sum(num1, num2)); // 41; 就会引入自定义的库import 'utils/math_utils.dart';
}

18.4 当库文件中和当前类中存在同名方法

// math_utils2.dart
int multiply(int num1, int num2) {
  return num1 * num2;
}
  • 不做处理会报错:
import 'utils/math_utils2.dart';

void main(List<String> arguments) {
  final num1 = 20;
  final num2 = 21;
  // ❌报错: The argument type 'int' can't be assigned to the parameter type 'double'.
  print(multiply(num1, num2));
}

double multiply(double num1, double num2) {
  return num1 * num2;
}

  • 使用as 关键字给库文件起一个别名 import '库的相对路径/库的名字 as 起别名:
import 'utils/math_utils2.dart' as mu2;

void main(List<String> arguments) {
  final num1 = 20;
  final num2 = 21;
  print(mu2.multiply(num1, num2));  // 420
}

18.5 默认情况下, 导入一个库时, 导入的是这个库的全部内容

  • show: 执行要导入的内容
  • hide: 隐藏某个要导入的内容, 导入其他内容
// math_utils3.dart
int minus(int num1, int num2) {
  return num1 - num2;
}

int _privateMinus(int num1, int num2) {
  return num1 - num2;
}

double devide(int num1, int num2) {
  return num1 / num2;
}
import 'utils/math_utils3.dart' show minus;         // 只导入minus,  其他的不导入
import 'utils/math_utils3.dart' hide devide;        // 只隐藏devide,  其他的都导入
import 'utils/math_utils3.dart' hide devide, minus; // 可以写多个

18.6 utils 文件夹内有多个库文件, 一一导入太麻烦, 所以只需要创建一个公共头文件utils.dart, 导入进来即可.

  • utils.dart内部格式为: export '库文件名称';
  • 外界想使用整个utils 文件夹内的东西, 直接import 'utils/utils.dart'即可.

18.7 下划线 (_) 开头则表示该标识符在库内是私有的, 同其他语言的private

当属性或者方法前面添加下划线, 就代表私有了, 外界就无法调用了, 就报错了:

void main(List<String> arguments) {
  print(_privateMinus(10, 11)); // ❌报错: The function '_privateMinus' isn't defined.
  print(minus(5, 1));           // 4
}

18.8 使用第三方的库

flutter 项目创建时候都会 自动创建pubspec.yaml文件, 在练习Dart时, 手动创建测试一下即可.

  • pubspec.yaml 添加需要以来的第三方库,
# pubspec.yaml
name: dart_learn
description: a libraries

# 添加依赖的第三方库
dependencies:
  http: ^0.13.5

# Dart SDK 的 版本
environment:
  sdk: '^2.12.0'
  • pub.dev中搜索需要使用的第三方库, 根据提示, 添加需要依赖的第三方,
  • 终端切换至utils路径下, 执行dart pub get 更新代码, 提示Got dependencies!代表着成功了,
  • math_utils.dart 文件中模拟网络请求,

首先要引入头文件,

import 'package:库名/库文件' as 别名

起别名是为了避免想通的sdk名称、方法名等等的冲突.

import 'package:http/http.dart' as http;

void main(List<String> args) async {
  var url = 'https://www.wanandroid.com/banner/json';
  var response = await http.get(Uri.parse(url));
  print("Response status: ${response.statusCode}");
  print("Response body: ${response.body}");
    /**
   * Response status: 200
   * Response body: {"data":[{"desc":"我们支持订阅啦~","id":30,
   * "imagePath":"https://www.wanandroid.com/blogimgs/42da12d8-de56-4439-b40c-eab66c227a4b.png",
   * "isVisible":1,"order":2,"title":"我们支持订阅啦~","type":0,"url":"https://www.wanandroid.com/blog/show/3352"},
   * {"desc":"","id":6,"imagePath":"https://www.wanandroid.com/blogimgs/62c1bd68-b5f3-4a3c-a649-7ca8c7dfabe6.png",
   * "isVisible":1,"order":1,"title":"我们新增了一个常用导航Tab~","type":1,"url":"https://www.wanandroid.com/navi"},
   * {"desc":"一起来做个App吧","id":10,"imagePath":"https://www.wanandroid.com/blogimgs/50c115c2-cf6c-4802-aa7b-a4334de444cd.png",
   * "isVisible":1,"order":1,"title":"一起来做个App吧","type":1,"url":"https://www.wanandroid.com/blog/show/2"}],
   * "errorCode":0,"errorMsg":""}
   */
}

19. 断言和懒加载

19.1 断言assert()

  • 断言assert() : assert() 的调用将会在生产环境的代码中被忽略掉。
  • 在开发过程中,assert(condition) 将会在 条件判断 为 false 时抛出一个异常。
  final num1 = 10;
  final num2 = 10;
  final num3 = 20;
  assert(num1 == num2); // 内部条件为true, 没问题
  assert(num1 == num3); // ❌错误: _AssertionError ... Failed assertion: line 14 pos 10: 'num1 == num3': is not true.)

19.2 懒加载

  • late 修饰不为空的变量, 已达到延迟加载的作用;
late String description
  • 在使用之前, 必须为其赋值, 不然会报错;
// ❌错误: The late local variable 'description' is definitely unassigned at this point.
print(description); 

19.3 库的懒加载

  • 使用deferred as关键字来指定:
import 'dart:math' deferred as math;

等到使用math库中的内容时(math.min(1, 2))即可, 懒加载的最大好处是可以减少APP的启动时间.

19.4 noSuchMethod

  • 如果调用了对象上不存在的方法或实例变量将会触发noSuchMethod 方法,
  • 可以重写noSuchMethod 方法来追踪和记录这一行为.
void main(List<String> arguments) {
  var a = A();
  a.getInfo();
}

class A implements B {
  @override
  String get info => throw UnimplementedError();
  // Unless you override noSuchMethod, using a
  // non-existent member results in a NoSuchMethodError.
  @override
  // 重写了noSuchMethod
  void noSuchMethod(Invocation invocation) {
    print('You tried to use a non-existent member: '
        '${invocation.memberName}');
  }
}

class B {
  final info = "this is b";
  String getInfo() => info;
}

20. 终端创建flutte项目

20.1 终端创建项目和IDE创建项目的区别

终端不会给你创建一堆没用的文件.

20.2 终端创建项目

  1. cd 到指定目录
  2. flutter create 项目名称
  3. 项目名称不能包含特殊字符、不能有大写、更不能采用驼峰命名
  4. 项目名称当由多个单词组成时, 下划线(_)拼接
  5. 创建flutter_learn项目

flutter_learn项目结构

20.3 flutter 项目文件说明

  1. .dart_tool: 记录某些东西(三方库等)的基本信息, 不需要手动配置
  2. .idea: 记录项目配置信息的文件, 不需要手动配置
  3. lib: 存放所有flutter的源码, 整个flutter项目的入口就是main.dart
  4. .metadata: 记录flutter版本信息的, 不需要手动编辑
  5. pubspec.yaml: 基本信息和引用说明, 需要手动编辑

20.4 运行一个flutter 项目

  • 点击VSCode 右上角三角号、终端输入flutter run、点击main 函数上面的run都能启动程序
  • 程序启动后会出现一个工具栏
      1. 闪电标志(hot reload) : 热重载 快捷键: control+F5
      1. 刷新标志(hot restart) : 热重启 快捷键: command+shift+F5
      1. 在使用热重载或者热重启时, 如果代码不生效, 试着检查下代码是否自动保存了, 没保存的需要保存下. 共有三种方式:
  1. 冷启动, 从0开始, 时间较长, 框架都从零开始加载 ;
  2. 热重载, 主要执行build
    • 例如: 点击flutter_learn demo, 屏幕中间计数器数字累加, 修改主题颜色, hot reload => 主题颜色会变, 但是计数器数字不变.
  3. 热重启, 重新运行整个App
    • 例如: 点击flutter_learn demo, 屏幕中间计数器数字累加, 修改主题颜色, hot restart => 主题颜色会变, 但是计数器数字重置.

20.5 widget

  • flutter 中理解万物都是widget
  • 当需要传入一个widget 类型时, 传什么都可以, 因为万物都是widget
  • widget 释义:
    • 百度: (不知名的)小器物,小装置,小玩意儿
    • 谷歌: 小部件

20.6 Material

  • 是一套谷歌的设计风格, 也可说是代码规范, 比如: 文字, 颜色, 排版, 动画, 填充等
  • flutter 高度集成了Material 风格的widget

接下来, 就可以进入flutter的开发啦...

结语

路漫漫其修远兮,吾将上下而求索~

作者简书

作者GitHub

.End