美文网首页
Flutter - 入门

Flutter - 入门

作者: Codepgq | 来源:发表于2021-03-27 09:47 被阅读0次

    Dart基础

    如果你有JSJavaKotlinSwift等语言的基础,入门几乎没啥子难度

    程序入口

    dartmain函数开始运行,国际惯例

    void main() {
        print("Hello World!");
    }
    

    由于dart中没有privatepublic等修饰符,所以约定俗成下划线开头表示私有。

    下面用一个类的声明讲解

    /// 声明
    class Hello {
    
        /// 私有变量
        String _privateName = "私有名称";
        
        /// 公开变量
        int age = 18;
        
        /// 私有方法
        _privateFunction() { 
            print("1");
        }
        
        /// 公开方法
        publicFunction() {
            print("1");
        }
        
        @protected
        refresh() {
            
        }
    }       
    

    setter/getter

    double _progress;
    
    double get progress => _progress;
    
    set progress(double newValue) {
        /// 自己的逻辑处理
        _progress = newValue;
    }
    

    final/const

    两者都是声明常量使用,区别是一个是在编译期,一个是运行期。

    import

    用于导入某些具体类/第三方SDK的实现

    基础数据类型

    dart支持数字、字符串、bool、数组(列表)、集合等数据。

    数字
    • int取值区间在-2^{53} ~ 2^{53}

    • double类型为64位的双精度浮点型

    方法 含义
    isFinite 是否为有限数字
    isInfinite 是否是无穷大
    isNan 是否是数字
    isNegative 是否为负数
    sign 如果数字小于0,返回-1;大于0返回1,如果本身是Nan或者0,返回0
    isEven 是否是偶数
    isOdd 是否是奇数
    abs 绝对值
    ceil 返回不小于该数字的最小整数
    floor 返回不大于当前数字的最大整数
    round 返回最接近当前数字的整数
    toDouble 转化为double类型
    字符串

    字符串可以用""表示也可以用''表示。

    在字符串中引用其他的变量

    • 成员变量

      "print("age is $age");"

    • 成员变量的成员变量、或者其他表达式

      print("name is ${jack.nickName}");

    字符串可以用 + 号连接

    bool

    dart中的if只支持bool只,不支持判空处理

    String g = null;
    
    /// 不合法
    if (g) {}
    
    /// 合法
    if(g!=null) {}
    
    集合(列表)
    • 有序
    • 可重复
    List list = [1,2,3,4,5, "6"]; 未指定的类型的情况下,可以插入任意值
    List<String> strList = ["a", "b", "c"]; // 指定类型的情况只能插入该类型的值
    List list2 = [-1, 0, ...list];
    
    List list3 = null;
    List list4 = [10, 11, ...?list3];
    
    方法 说明
    generate 根据数据创建一个表
    length 列表长度
    sort 排序,根据传入的compare判断条件
    indexOf 获取下表,根据传入的条件,正序遍历找到就返回
    lastIndexWhere 从后向前遍历,根据传入条件找到第一个返回并结束
    Set 集合
    • 无序
    • 不可重复
    Set<String> name = {"Jack", "Mark"};
    name.add("Lucky");
    
    方法 说明
    lookup 查找某个元素
    contains 是否包含某个值
    difference 两个集合进行比较,返回不同的元素
    Map

    键值对的方式进行数据的存储,键唯一,值可以不唯一。

    未指定value的类型情况下,值可以是任意类型

    Map map = {
        "age": 19,
        "name": "Hello",
        "info": {}
    };
    
    //add
    map['address'] = "";
    
    //put
    String name = map['name'];
    
    方法 说明
    putIfAbsent 根据传入的key查看值是否存在,存在就返回,不存在就插入在返回
    isEmpty 是否为空
    isNotEmpty 是否不为空
    length 返回map的长度
    containsKey 是否包含某个key
    containsValue 是否包含某个value
    enum

    枚举,这里枚举值的类型是int,默认从0开始,并且不可以设置起始值

    enum Style {
        normal,
        vip
    }
    
    常用操作符
    • ..

      联级操作符

      Object obj = Object();
      obj
        ..name=""
        ..age=18
        ..address = "";
      
    • ??

      判断前面的值/对象是否为空,为空就是用??后面的值

      int a = null;
      int b = 1;
      print("${a ?? "hello"}"); // hello
      print("${b ?? "hello"}"); // 1    
      
    • ??=

      判断是否已经初始化

      int a = 2;
      a ??= 3;
      print("$a"); // 2, 如果是 int a = null; 那么结果就是 3
      
    • ~/

      整除

      print("${5.2 ~/ 3.3 }"); // 1
      

    var和dynamic

    var会自动推导出类型,var只是语法糖,运行的时候会根据值推到类型

    dynamic表示动态类型,不做任何检测,真正的动态类型

    函数方法

    dart中的函数声明格式为返回值 函数名(参数列表) 修饰符{ 函数体}

    int test(int age, {String name, String address}) async {
         await Future.delay(Duration(seconds: 1));
       return 1;
    }
    
    // int 返回值类型
    // test 函数名称
    // int age 参数(必填,且顺序固定
    // String name 参数 (非必填,顺序不要求
    // String address 参数 (非必填,顺序不要求
    // async 标记是异步方法
    // {}内部就是函数体
    

    类、接口、继承

    • abstract class 接口类

      内部的函数只用声明就够了

    • class

      内部的函数需要实现

    接口

    dart中没有接口关键字,类也可以作为接口,只需要使用implements实现就好

    继承

    extends,使用这个修饰。

    demo
    abstrace class Interface {
        void doA();
        void doB();
    }
    
    class InterfaceClass {
        void doC() {}
        void doD() {}
    }
    
    class Demo implements Interface, InterfaceClass {
        void doA() {}
        void doB() {}
        void doC() {}
        void doD() {}
    }
    

    mixins

    混入,混入是的基础顺序是从右到做依次执行,也就是说最后混入的类,如果遇到同名函数,最优先执行,而且和super方法是否执行有关。

    异常

    通过try..catch捕获异常,通过throw抛出异常

    异常类型 说明
    FormatException 当字符串或某些其他数据没有预期格式,且无法解析活处理时抛出
    IntergerDivisionByZeroException 当数字除与0的时候抛出
    IOException 输入、输入相关的异常
    IsolateSpawnException 无法创建隔离时抛出
    Timeout 等待异步结果是,如果发生超时,则抛出

    Isolate

    Dart本身是单线程执行,但还是增加了Isolate提供跨线程的真异步操作。因为在dart线程中不会共享内存,所以也不会存在死锁,从而而导致了Isolate之间的数据只能通过port的端口方式发送接口,所以Isolate也称之为隔离的执行。Dart中提供了Isolate的封装,便于我们使用

    Isolate主要在 dart:isolate包中,其中

    • Isolate用于dart执行上下文隔离
    • ReceivePort和SendPort一起,是通信的唯一方式
    • SendPort将消息发送到其他ReceivePort
    demo
    Isolate isolate;
    void doIsolate() async {
      var receive = ReceivePort();
      isolate = await Isolate.spawn(echoResult, receive.sendPort);
      receive.listen((message) { 
        print("message is $message");
      });
    }
    
    /// 处理消息
    void echoResult(SendPort port) {
      final msg = "Hello world";
      Timer.periodic(const Duration(seconds: 1), (timer) { 
        port.send(msg);
      });
    }
    
    void kill() {
      isolate.kill(priority: Isolate.immediate);
      isolate = null;
    }
    

    除了这以外,还提供了一个更为简单的处理方法compute。需要注意的是compute方法运行中的方法必须是顶级方法或者静态方法

    testCompute() {
      compute(execString, "hello").then((value) {
        print("isolate compute $value "); ///isolate compute hello world
      });
    }
    
    /// 此为顶级函数
    Future execString(value) async {
      await Future.delayed(Duration(milliseconds: 1000));
      return value + " world";
    }
    

    Zone

    表示Dart运行的环境,类似于一个沙盒。通过Zone我们还可以监听到全局范围内捕获到的异常

    runZoned(() {
        runApp(FlutterApp());
    }, onError: (Objects obj, StackTrace stack) {
        print(obj);
        print(stack);
    });
    

    异步

    • async/await
    • Stream

    扩展方法

    和swift一样,可以对原有类进行扩展

    demo
    extension ExtendsFun on String {
        int parseToInt() {
            return int.tryParse(this);
        }
    }
    
    main() {
        String num = "4";
        print(  num.parseToInt()); // 4
    }
    

    常用控件

    Flutter中的Widget可以分为两类,StatelessWidgetStatefulWidget。分表表示无状态和有状态的Widget

    两者都是通过widget.build方法构建UI,不同之处StatefulWidget可以进行刷新操作,生命周期也略有不同。

    具体的类型控件自行查阅相关文档

    列举一些常用的Widget

    控件 描述
    Container 只有一个子Widget、默认充满,是一个集合了很多属性的容器视图,包含了:padding、margin、color、width、height、decoration等
    Padding 只有一个子Widget,只包含Padding的设置。多用于控制边距
    Center 只有一个子Widget,被其包起来的Widget会居中显示
    Stack 有多个子Widget,是一个列表,列表末尾的child会显示在最顶层
    Column 有多个子Widget,是一个列表,默认是从屏幕上至下,垂直排列
    Row 有多个子Widget,是一个列表,默认是从屏幕左至右,水平排列
    Expanded 只有一个子Widget,在Column和Row中撑满余下空间,如果要均分,可以设置其的flex属性
    ListView 和Column类似,区别之处就是可以超出屏幕范围,加载也会根据屏幕显示区域进行处理

    UI更新

    在实际开发中我们推送尽可能的使用StatelessWidget,但是由于它是无状态的,所以就针对他的刷新机制推出了很多实现方案:Reduxproviderblocprovide。这里推荐使用官方推崇的Provider

    StatefulWidget的生命周期

    生命周期

    路由跳转

    使用路由跳转时候可以使用pushName或者push方法,两个都可以进行导航操作;如果使用pushName,在必须在根App处进行定义,使用Push则没有这方面的要求

    demo
    class MyApp extends StatelessWidget {
        @override
        Widget build(BuildContext context) {
            return MaterialApp(
                home: HomePage(),
                routes: {
                "weather": (_) => WeatherPage(),
                }
            );
        }
    }
    
    // pushName
    Navigator.pushName(context, 'weather');
    
    // push
    Navigator.push(context, MaterialPageRoute(build: (context) => WeatherPage()));  
    

    相关文章

      网友评论

          本文标题:Flutter - 入门

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