Flutter小白实操之Dart简介

以下内容参考《Flutter实战·第二版》,仅为个人学习、熟悉Dart语言,不同版本可能有稍微不一样。

///
/// 例子来源:
/// 《Flutter实战·第二版》https://book.flutterchina.club/chapter1/dart.html
///
/// 环境:
/// Flutter 3.10.1 • channel stable • https://github.com/flutter/flutter.git
/// Framework • revision d3d8effc68 (7 days ago) • 2023-05-16 17:59:05 -0700
/// Engine • revision b4fb11214d
/// Tools • Dart 3.0.1 • DevTools 2.23.1
///

调用

void main() {
  TestFunction().sayHi("aaa");
  TestFunction().doSomething(() => print("hhh"));
  TestFunction().say("A", "hello"); // A says hello
  TestFunction().say("A", "hello", "bus");// A says hello with a bus
  TestFunction().sayHello(who: "Bob"); // Bob say hello

  Dog()..eat()..walk();
  // flutter: eat
  // flutter: walk with 4 foot
  Dog().doSomething();
  // flutter: a Dog can do like this:
  // flutter: eat
  // flutter: walk
  // flutter: walk with 4 foot
  
  TestAsync().testFutureDelayed();
  TestAsync().testFutureWait();
  TestAsync().testAsync();
  TestAsync().testStream();
}

Var

class TestVar {
  void defVar() {
    var t = "hello, world!";
    // 下面代码在dart中会报错,因为变量t的类型已经确定为String,
    // 类型一旦确定后则不能再更改其类型。
    //t = 1000;
  }

  void dynamicAndObject() {
    // dynamic与Object声明的变量都可以赋值任意对象,且后期可以改变赋值的类型,这和 var 是不同的,如:
    dynamic t;
    Object x;
    t = "hello, world!";
    x = "hi, world!";
    //下面代码没有问题
    t = 1000;
    x = 1000;

    // dynamic与Object不同的是dynamic声明的对象编译器会提供所有可能的组合,
    // 而Object声明的对象只能使用 Object 的属性与方法, 否则编译器会报错,如:
    Object b = "";
    // 正常
    print(t.lenght);
    // 报错 The getter 'lenght' isn't defined for the type 'Object'.
    //print(b.lenght);

    // dynamic 的这个特点使得我们在使用它时需要格外注意,这很容易引入一个运行时错误,
    // 比如下面代码在编译时不会报错,而在运行时会报错:
    print(t.xx); // t是字符串,没有"xx"属性,编译时不会报错,运行时会报错
  }

  /// 一个 final 变量只能被设置一次,两者区别在于:
  /// const 变量是一个编译时常量(编译时直接替换为常量值),final变量在第一次使用时被初始化。
  void finalAndConst() {
    // 可以省略String这个类型声明
    // 有警告: Use 'const' for final variables initialized to a constant value.
    final str = "I am final String";
    // final String str = "I am final String";
    const str1 = "I am const String";
    // const String str2 = "I am const String";
  }

  void nullSafety() {
    // int i; // i = null
    // print(i*8); //运行时错误

    int i = 8; // 默认不空,定义后初始化
    int? j; // 可空,使用前判空

    // 使用late后续初始化,使用前必须初始化,否则报错
    late int k;
    // print(k); // The late local variable 'k' is definitely unassigned at this point.
    k = 9;
    print(k);

    // 如果一个变量我们定义为可空类型,在某些情况下即使我们给它赋值过了,但是预处理器仍然有可能识别不出,
    // 这时我们就要显式(通过在变量后面加一个”!“符号)告诉预处理器它已经不是null了,比如:
    Function? fun;
    if (i != null) {
      print(i! * 8); //因为已经判过空,所以能走到这 i 必不为null,如果没有显式申明,则 IDE 会报错
    }
    if (fun! != null) {
      fun!();
    }

    fun?.call(); // fun 不为空时则会被调用
  }
}

Function

可选参数[]和可选命名参数({xx,xx,...})还是不错的

class TestFunction {
  // 不指定返回类型,此时默认为dynamic,不是bool
  /*bool */isNoNull(String str) {
    return str.isNotEmpty;
  }
  // 简写
  bool isNull(String str) => str.isEmpty;

  // 函数作为变量
  var sayHi = (str) {
    print(str);
  };

  // 参数为函数
  void doSomething(var callback) {
    callback(); // 执行函数
  }

  // 用[]标记为可选的位置参数,并放在参数列表的最后面
  String say(String from, String msg, [String? device]) {
    var result = "$from says $msg";
    if (device != null) {
      result = "$result with a $device";
    }
    return result;
  }

  // 可选的命名参数,使用{param1, param2, …},放在参数列表的最后面,用于指定命名参数
  // 注意,不能同时使用可选的位置参数和可选的命名参数
  void sayHello({required String who}) {
    print("$who say hello");
  }
}

mixin

class Dog with Eat, Walk {
  @override
  walk() {
    print("walk with 4 foot");
  }

  doSomething() {
    print("a Dog can do like this: ");
    eat();
    super.walk();
    walk();
  }
}
class Man extends Persson with Eat, Walk, Code {}

class Persson {
  say() {
    print("say");
  }
}

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

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

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

Async

class TestAsync {
  void testFutureDelayed() {
    print("Future.delayed 2s after exec something");
    Future.delayed(const Duration(seconds: 2), () {
      print("Future.delayed hello");
      throw AssertionError("delayed error"); // 根据是否有onError或catchError执行
    }).then((data) {
      // 成功走这里
      print("Future.delayed success");
    }, onError: (e) {
      print("Future.delayed onError $e"); // 加了onError,不走catchError
    }).catchError((e) {
      // 失败走这里 then没加onError,不走then,走catchError
      print("Future.delayed catchError $e");
    }).whenComplete(() {
      print("Future.delayed complete"); // 无论成功或失败都走这里
    });

    // flutter: Future.delayed 2s after exec something
    // flutter: Future.delayed hello
    // flutter: Future.delayed onError Assertion failed: "delayed error"
    // flutter: Future.delayed complete
  }

  // 等待多个异步任务都执行结束后才进行一些操作
  // Future.wait([]), 数组中所有Future都执行成功后,才会触发then的成功回调, 只要有一个Future执行失败,就会触发错误回调
  void testFutureWait() {
    print("Future.wait start after 4s show something");
    Future.wait([
      Future.delayed(const Duration(seconds: 2), () {
        return "Hi";
      }),
      Future.delayed(const Duration(seconds: 4), () {
        return " Bob";
      }),
    ]).then((results) {
      print("Future.wait ${results[0]}${results[1]}");
    }).catchError((e) {
      print(e);
    }).whenComplete(() {
      print("Future.wait complete");
    });

    // flutter: Future.wait start after 4s show something
    // flutter: Future.wait Hi Bob
    // flutter: Future.wait complete
  }

  void testAsync() {
    testAsync1();
    testAsync2();
    testAsync3();
    testAsync4();

    // flutter: testAsync1
    // flutter: testAsync2 pre //有await,after
    // flutter: testAsync3
    // flutter: testAsync4 pre //没有await,直接after
    // flutter: testAsync4 after //没等待
    //
    // flutter: testAsync2 in //等待2s后
    // flutter: testAsync2 after
    // flutter: testAsync4 in
  }

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

  void testAsync2() async {
    print("testAsync2 pre");
    await Future.delayed(const Duration(seconds: 2), () {
      print("testAsync2 in");
    });
    print("testAsync2 after");
  }

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

  void testAsync4() async {
    print("testAsync4 pre");
    /*await*/ Future.delayed(const Duration(seconds: 5), () {
      print("testAsync4 in");
    });
    print("testAsync4 after");
  }

  void testStream() {
    Stream.fromFutures([
      // 1秒后返回结果
      Future.delayed(const Duration(seconds: 1), () {
        return "Stream hi 1";
      }),
      Future.delayed(const Duration(seconds: 2), () {
        throw AssertionError("Stream error");
      }),
      Future.delayed(const Duration(seconds: 3), () {
        print("Stream hi 3");
      }),
    ]).listen((data) {
      print("Stream listen $data");
    }, onError: (e) {
      print("Stream error $e");
    }, onDone: () {
      print("Stream Done");
    });
    // flutter: Stream listen Stream hi 1
    // flutter: Stream error Assertion failed: "Stream error"
    // flutter: Stream hi 3
    // flutter: Stream listen null
    // flutter: Stream Done
  }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容

  • 书籍 《Flutter实战·第二版》](https://book.flutterchina.club/[https...
    wg689阅读 516评论 0 1
  • [TOC] Flutter简介 Flutter 是 Google推出并开源的移动应用开发框架,主打跨平台、高保真、...
    修_远阅读 214评论 0 0
  • 前言:学习 Flutter 有一段时间了,本篇文章主要是记录下 Flutter 学习历程的一些心得和开发体验,罗列...
    沉江小鱼阅读 4,212评论 3 29
  • 我写了一本 《Flutter实战》 推荐给大家。在线阅读地址:https://book.flutterchina...
    lazydu阅读 12,915评论 4 15
  • Flutter环境搭建这里只介绍在macOS中Flutter的环境搭建,如需了解windows下的Flutter开...
    grr1314阅读 531评论 2 0