美文网首页
Flutter 学习小记

Flutter 学习小记

作者: plantseeds | 来源:发表于2020-04-22 16:23 被阅读0次

    学习自视频 [千锋]2020全新Dart Flutter开发教程

    1. var 声明变量,如果初始化时不指定类型(即只声明不赋值),则其是动态类型 dynamic,可以给其赋值任意类型的值。如果指定了类型,则其类型就确定了,后续不能更改。

      var a; // 初始化没有指定类型,a 为动态类型(相当于:dynamic a;)
      a = 2; // ✅
      a = 'hello'; // ✅
      
      var b = 1; // 初始化就确定了值的类型,b的类型不能再更改(相当于:int b = 1;)
      b = 'hello'; // ❌
      
    2. final 修饰的变量在声明时必须初始化,且不能被再次赋值。

      void main() {
        int a; // ✅
        final a = 1; ✅
        final a; // ❌
      }
      
    3. const 声明的必须是 编译器常量

      int getNum() { return 1; }
      
      void main() {
        final a = getNum(); // ✅
        const b = getNum(); // ❌
      }
      
    4. intdouble 都是 num 类型的子类

      int a = 1;
      a = 1.1; // ❌ (不能把 double 类型赋值给 int 类型)
      
      num c = 3; // 用 num 类型声明 c,c 既可以是 int 类型,也可以是 double 类型
      c = 3.3 // ✅
      
    5. 通过提供一个 r 前缀,可以创建一个 原始raw 字符串

      var s = r"In a raw string, even \n isn't special.";
      print(s); // 不会产生换行效果,打印结果为:In a raw string, even \n isn't special.
      
    6. 如果一个对象等于 null,调用它的方法,运行时会报错

      List a;
      
      a.add(1); // ❌ Unhandled Exception: NoSuchMethodError: The method 'add' was called on null.
      
      a?.add(1); // ✅ 由于 ? 判断出 a 等于 null,便直接忽略掉后续操作:add()
      
    7. const 定义一个不可变的 List,如果执行修改操作,运行时会报错

      List a = const [1, 2];
      a.add(3); // ❌ Unhandled Exception: Unsupported operation: Cannot add to an unmodifiable list
      
    8. asisis! 操作符在运行时用于检查类型非常方便

      as:类型转换
      is:当对象是相应类型时返回 true
      is!:当对象不是相应类型时返回 true
      
    9. 赋值操作符 ??= ,仅当变量为 null 时赋值

      var a = 1;
      a ??= 2; // 
      print(a) // 输出 1
        
      var b;
      b ??= 2;
      print(b) // 输出 2
      
    10. 级联符号 ..

    querySelector('#confirm') // 获取一个对象
      ..text = 'Confirm' // 使用它的成员
      ..classes.add('important')
      ..onClick.listen((e) => window.alert('confirmed!'));
    

    上述代码相当于:

    var button = querySelector('#confirm');
    button.text = 'Confirm';
    button.classes.add('important');
    button.onClick.listen((e) => window.alert('confirmed'));
    

    可以看出,遵循级联符号的代码都是对第一个方法返回的 button 对象进行操作,而忽略任何可能返回的后续值。

    级联操作符可以嵌套

    final addressBook = (AddressBookBuilder()
          ..name = 'jenny'
          ..email = 'jenny@example.com'
          ..phone = (PhoneNumberBuilder()
                ..number = '415-555-0100'
                ..label = 'home')
              .build())
        .build();
    

    注意

    var a = StringBuffer();
    a.write('foo') // 这儿是用的'.',而非级联运算符'..'
     ..write('bar'); // ❌ 第一个 a.write() 返回值是 void,返回值为 void 的方法则不能使用级联运算符
    
    
    var b = StringBuffer();
    b
      ..write('foo')
      ..write('bar'); // ✅
    
    1. 使用 dynamic 方式定义方法

      getUser(name) => '$name is very good!'; // 参数和返回值类型都是 dynamic 的
      
      print(getUser('zhangsan'));
      
    2. 方法的参数:

      1. 必要参数;

        getProduct(num id, String description) {};
        
        getProduct(1, 'description'); // ✅
        getProduct(id: 1, description: 'description'); // ❌ 调用时 不能写参数名
        
      2. 可选参数:

        1. 命名参数,表达形式:{k: v} 键值对;

          getProduct({bool flag, String name}) {};
          
          getProduct(); // ✅
          getProduct(flag: true); // ✅
          getProduct(name: 'zhangsan'); // ✅
          getProduct(flag: true, name: 'zhangsan'); // ✅
          
        2. 位置参数,表达形式:[type name]

          getProduct([bool flag, String name]) {};
          
          getProduct(true); // ✅
          getProduct(true, 'zhangsan'); // ✅
          getProduct(null, 'zhangsan'); // ✅
          getProduct('zhangsan'); // ❌ 必须传前面的 flag 参数,否则会提示 String和bool 类型不匹配
          getProduct(flag: true, name: 'zhangsan'); // ❌ 调用时 不能写参数名
          

      注意:不能同时使用可选的位置参数和可选的命名参数。必要参数定义在参数列表前面,可选参数则定义在必要参数后面。

    3. Dart 中的构造方法是不支持重载的,可以通过 命名的构造方法 来实现构造方法的重载:

      class Student {
        String name;
        final int gender;
      
        Student(this.name, this.gender);
      
        // 命名的构造方法
        Student.withName(this.gender) {}
      }
      

      注意:用 final 修饰的属性 gender,不能用如下写法来初始化:

      Student(String name, int gender) {
        this.name = name;
        this.gender = gender; // ❌ 'gender' can't be used as a setter because it is final.
      }
      
    4. 常量构造方法,需要把该类的构造方法用 const 修饰,并且该类的所有实例属性必须是 final

      class Student {
        final String name;
        final int age;
      
        // 常量构造方法 const
        const Student(this.name, this.age);
      }
      
      const s = Student('zhangsan', 18);
      
    5. getter 方法

      class Student {
        int _age;
        
        int get age => _age; // 或 int get age { return _age; }
      }
      
    6. setter 方法

      class Student {
        int _age;
        
        set age(int age) => _age = age; // 或 set age(int age) { _age = age; }
      }
      
    7. factory 工厂构造函数:使用 factory 关键字标识的构造函数,意味着使用该构造函数 构造类的实例时,并非总是会返回新的实例对象。例如,工厂构造函数可能会从缓存中返回一个实例,或者返回一个子类型的实例。

      class Person {
        static final Map<String, Person> _cache = {};
      
        // 工厂构造方法
        factory Person() {
          return _cache.putIfAbsent('p', () => Person._inner());
        }
      
        // 命名的私有构造方法
        Person._inner();
      }
      
      var a = Person(); // 缓存中没有,a 是新建的实例,并存入 缓存 _cache 中
      var b = Person(); // 缓存中有了,b 是从缓存 _cache 中读取的实例
      print(a == b); // 输出 true
      
    8. 如果类实现了 call 方法,则该类的对象可以作为方法使用

      class Student {
        call(int x, int y) { // 可以不加参数
          print(x + y);
        }
      }
      
      var a = Student();
      a(1, 2); // 输出 3
      
    9. abstract 抽象类中的抽象方法,子类必须重写

      abstract class Person {
        say() {} // 普通方法或属性
      
        sleep(); // 抽象方法
      }
      
      class Student extends Person {
        @override
        sleep() {
          // TODO: implement sleep
          return null;
        }
      }
      

      抽象类常用于声明接口方法,通常不能被实例化,但有时也会有具体的方法实现。如果想让抽象类同时可被实例化,可以为其定义 工厂构造函数

    10. Dart 是单继承,但一个类可以 实现implements 多个接口。

      class Point implements Comparable, Location {...}
      
    11. import 时使用 as 可以为模块中的代码重命名(可以避免不同模块中的同名代码冲突),白可以使用 showhide 关键字来 指定 暴露或隐藏 模块中的部分代码。

      import './one.dart' as lib1;
      import './two.dart' as lib2 show method2; // lib2 中仅 method2 方法可见
      import './three.dart' as lib3 hide method3, mehtod33; // lib3 中的 method3 和 method33 方法不可见
      
    12. Container 中嵌套 Container,如果不设置 外层 Containeralignment,则内层的 Container 会填满外层的 Container,内层 Container 设置的宽高会被忽略。

    相关文章

      网友评论

          本文标题:Flutter 学习小记

          本文链接:https://www.haomeiwen.com/subject/nuziihtx.html