Flutter基础入门

04-01 阅读 0评论

文章目录

  • 一、Flutter基础知识
    • 1.Flutter简介和发展历史
    • 2.Flutter安装和配置
    • 3.Dart语言基础知识
      • Dart语言特性
      • Dart基本语法
      • 空安全 Null safety
      • Dart异步原理
      • 4.Flutter项目结构和文件组织方式
      • 5.Flutter Widgets和布局基础
      • 二、Flutter进阶知识
        • 1.Flutter状态管理和数据传递
        • 2.Flutter动画和过渡效果
          • 隐式(全自动)动画
            • AnimatedContainer
            • TweenAnimationBuilder
            • 显示(手动控制)动画
              • 自定义显示动画:AnimatedBuidler
              • 3.Flutter网络请求和数据解析
                • 网络请求框架
                • 数据解析
                • 4.Flutter本地存储和数据缓存
                • 5.Flutter渲染和性能优化
                  • 渲染流程
                  • 常见的内存溢出和内存泄漏的场景
                  • 优化检测工具
                  • Flutter布局优化
                    • 常规优化
                    • 深入光栅化优化
                    • Flutter内存优化
                    • 6.Flutter代码结构和代码质量把控
                    • 三、常用插件和第三方库
                      • 好用的状态管理
                      • 好用的网络请求
                      • 好用的图片加载
                      • 好用的音视频
                      • 好用的控件
                      • 好用的工具类
                      • 好用的动画
                      • 好用的数据存储
                      • 好用的事件传递
                      • 好用的三方sdk
                      • 好用的编译器插件
                      • 四、可能有用的小技巧

                        一、Flutter基础知识

                        1.Flutter简介和发展历史

                        Flutter是一款由Google开发的移动应用程序开发框架,可用于开发高性能、跨平台的移动应用程序。Flutter使用Dart编程语言,并提供了丰富的UI组件和工具,使得开发者可以快速构建漂亮、响应式的用户界面和高质量的应用程序。

                        Flutter基础入门,Flutter基础入门,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,使用,我们,访问,第1张
                        (图片来源网络,侵删)

                        Flutter的发展历史可以分为以下几个阶段:

                        • 2011年,Dart语言项目启动,旨在提供一种适用于Web开发的高性能编程语言。

                        • 2015年,Flutter项目启动,旨在使用Dart语言构建高性能、跨平台的应用程序。

                        • 2017年,Flutter的第一个Alpha版本发布,开发者可以开始尝试使用Flutter构建应用程序。

                        • 2018年,Flutter的第一个稳定版本发布,得到了广泛的认可和采用。

                        • 2019年,Flutter 1.5发布,增加了对iOS13和Android Q的支持,以及许多其他改进和 新功能。

                          Flutter基础入门,Flutter基础入门,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,使用,我们,访问,第2张
                          (图片来源网络,侵删)
                        • 2020年,Flutter 1.20发布,引入了新的Web支持和iOS14和Android 11的支持,以及其他改进和新功能。

                        • 2021年,Flutter2.0发布,引入了许多重要的新功能,包括全新的Web支持、桌面应用程序支持、Flutter for Windows等。

                        • 2023年,Flutter3.0发布,引入了许多重要的新功能,包括全新的Web支持、桌面应用程序支持、Flutter for Windows等。

                          截止到2023年3月,由于Flutter生态系统的不断发展,Flutter在Google Play Store和Apple App Store上已经有超过400,000款应用程序上线。同时,Flutter还正在扩展到其他领域,例如Web开发和桌面应用程序开发,这些领域的应用程序数量也在不断增长。由于Flutter是一个开源框架,许多公司和个人也在使用Flutter构建自己的应用程序,并且Flutter的生态系统也在不断扩大,因此Flutter上线的应用程序数量可能会随着时间的推移而继续增长。

                          2.Flutter安装和配置

                          以下是安装和配置Flutter的步骤,以Windows为例:

                          1. 下载Flutter SDK

                          可以在Flutter的官方网站上下载Flutter SDK。下载完成后,将其解压到您选择的目录中,例如在Windows上,您可以将其解压到 C:\src\flutter。

                          Flutter基础入门,Flutter基础入门,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,使用,我们,访问,第3张
                          (图片来源网络,侵删)
                          1. 配置Flutter环境变量

                            将Flutter SDK的路径添加到PATH环境变量中,以便在终端中可以使用flutter命令。例如,在Windows上,您可以将C:\src\flutter\bin添加到系统环境变量的PATH变量中。

                          2. 下载开发工具并安装Flutter插件

                            如果您使用的是Android Studio或IntelliJ IDEA,您需要安装Flutter插件以便在IDE中开发Flutter应用程序。打开IDE,进入插件设置,搜索“Flutter”,然后安装并重启IDE即可。

                          3. 运行Flutter Doctor

                            打开终端或命令提示符,并输入“flutter doctor”命令,以检查Flutter环境的配置情况。Flutter doctor会检查您的环境并给出建议以解决任何缺失的依赖项或配置问题。

                          4. 配置Android开发环境

                            如果您要在Flutter中开发Android应用程序,您需要安装并配置Android开发环境。您可以在Android开发者网站上获取有关如何安装和配置Android开发环境的更多信息。

                          以上是在Windows上安装和配置Flutter的基本步骤。完成这些步骤后,您就可以开始使用Flutter构建应用程序了。

                          3.Dart语言基础知识

                          Dart语言特性

                          • Dart 的特性

                            Dart 是少数同时支持 JIT(Just In Time,即时编译)和 AOT(Ahead of Time,运行前编译)的语言之一。语言在运行之前通常都需要编译,JIT 和 AOT 则是最常见的两种编译模式。

                            • JIT 在运行时即时编译,在开发周期中使用,可以动态下发和执行代码,开发测试效率高,但运行速度和执行性能则会因为运行时即时编译受到影响。

                            • AOT 即提前编译,可以生成被直接执行的二进制代码,运行速度快、执行性能表现好,但每次执行前都需要提前编译,开发测试效率低。

                              总结来讲,在开发期使用 JIT 编译,可以缩短产品的开发周期。Flutter 最受欢迎的功能之一热重载,正是基于此特性。而在发布期使用 AOT,就不需要像 React Native 那样在跨平台 JavaScript 代码和原生 Android、iOS 代码之间建立低效的方法调用映射关系。所以说,Dart 具有运行速度快、执行性能好的特点。

                            • 内存分配与垃圾回收

                              Dart VM 的内存分配策略比较简单,创建对象时只需要在堆上移动指针,内存增长始终是线性的,省去了查找可用内存的过程。

                              Dart 的垃圾回收,则是采用了多生代算法。新生代在回收内存时采用“半空间”机制,触发垃圾回收时,Dart 会将当前半空间中的“活跃”对象拷贝到备用空间,然后整体释放当前空间的所有内存。回收过程中,Dart 只需要操作少量的“活跃”对象,没有引用的大量“死亡”对象则被忽略,这样的回收机制很适合 Flutter 框架中大量 Widget 销毁重建的场景。

                            • 单线程模型

                              Dart 中并没有线程,只有 Isolate(隔离区)。Isolates 之间不会共享内存,就像几个运行在不同进程中的 worker,它们通过事件循环(Event Looper)在事件队列(Event Queue)上传递消息通信。所以如果想要在 Dart 中实现并发是可以通过 Isolate 实现的。Isolate 的这种类似于线程但不共享内存,独立运行的 worker的机制,就可以让 Dart 实现无锁的快速分配。

                            • 无需单独的声明式布局语言

                              Dart 声明式编程布局易于阅读和可视化,使得 Flutter 并不需要类似 JSX 或 XML 的声明式布局语言。所有的布局都使用同一种格式,也使得 Flutter 很容易提供高级工具使布局更简单,就突出一个上手简单。

                              Dart基本语法

                              • 主函数(入口函数)
                                void main(List arguments) {
                                	print('Hello world! ${arguments}');
                                }
                                
                                • 函数
                                  // 1,函数创建
                                  // 2,函数传值
                                  // 3. 可选参数
                                  printName(String name, int age, [String sex = '女']) {
                                  	print("name is ${name}, age is ${age}, sex is ${sex}")
                                  }
                                  // 4. 命名函数
                                  printInfo({name, age=4, sex}) {
                                  	print("name is ${name}, age is ${age}, sex is ${sex}")
                                  }
                                  void main(List arguments) {
                                  	printName('果果', 18);
                                  	printInfo({name: '果果', age: 4, sex: '女'});
                                  }	
                                  
                                  • 基本类型

                                    Dart支持的基础数据类型和其他语言基本一样

                                    // 基本类型
                                    // int
                                    int age = 20;
                                    // double
                                    double count = 10.0;
                                    // String
                                    String name="果果";
                                    // bool
                                    bool flag = true;
                                    // List
                                    List list = [1,2,3,4,5,6];
                                    // Set
                                    Set set = new Set();
                                    set.addAll(list);
                                    // Map
                                    Map user = {'name': 'bajie', 'age': 18};
                                    // 常量
                                    const
                                    final
                                    /*
                                    * 区别:
                                    * const 必须先赋初值
                                    * final 可以后面赋值一次
                                    */ 
                                    // 变量
                                    var
                                    // 类型可推导
                                    => var user = {'name': '果果', 'age': 4};
                                    print("${user['name']}")
                                    
                                    • 面向对象
                                      // 创建一个类
                                      // lib/animal.dart
                                      class Animal {
                                        String? name;
                                        Animal({this.name});
                                        Animal.fromJson(Map json) {
                                          name = json['name'];
                                        }
                                        Map toJson() {
                                          final Map data = {};
                                          data['name'] = name;
                                          return data;
                                        }
                                        void eat() {
                                          print('$name is eating!');
                                        }
                                      }
                                      // main.dart
                                      void main() {
                                      	Animal a = Animal(name: '果果');
                                      	a.eat();
                                      }
                                      输出结果:果果 is eating
                                      
                                      • 类的继承
                                        // 继承一个类
                                        // lib/cat.dart
                                        class Cat extends Animal {
                                          
                                        }
                                        void main() {
                                          Cat cat = Cat();
                                          cat.name = "colala";
                                          cat.eat();
                                        }
                                        输出结果:colala is eating
                                        

                                        多态

                                        // lib/cat.dart
                                        class Cat {
                                        	// 重写一个方法
                                        	drink() {
                                            print('$name is drinking!');
                                          }
                                        } 
                                        void main() {
                                          Cat cat = Cat();
                                          cat.name = "colala";
                                          cat.eat();
                                          cat.drink();
                                        }
                                        输出结果:colala is eating
                                        输出结果:colala is drinking
                                        
                                        • 类的实现

                                          Dart语言中没有接口(interface)的关键字,但是有实现(implements)关键字,Dart中可以将类(是否为抽象无关)当做隐式接口直接使用,当需要使用接口时,可以声明类来代替。

                                          // 抽象类作为接口
                                          abstract class Sleep{ 
                                            void sleep();
                                          }
                                          // 普通类作为接口
                                          class Play{ 
                                            void play(){}
                                          }
                                          class Cat extends Animal implements Sleep, Play {
                                            @override
                                            void eat() {
                                              print("eat");
                                            }
                                            @override
                                            void sleep() {
                                              print(" is sleeping");
                                            }
                                            @override
                                            void play() {
                                              print("is beating colala");
                                            }
                                          }
                                          void main() {
                                            var cat = = Cat();
                                            cat.name = "果果";
                                            cat.eat();
                                            cat.sleep();
                                            cat.play();
                                          }
                                          输出结果:果果 is eating
                                          输出结果:果果 is sleeping
                                          输出结果:果果 is beating colala
                                          
                                          • 类的混入

                                            mixin一般用于描述一种具有某种功能的组块,而某一对象可以拥有多个不同功能的组块。

                                            mixin用于修饰类,和abstract类似,该类可以拥有成员变量、普通方法、抽象方法,但是不可以实例化。

                                            mixins不是一种在经典意义上获得多重继承的方法。

                                            mixins是一种抽象和重用一系列操作和状态的方法。

                                            它类似于扩展类所获得的重用,但它与单继承兼容,因为它是线性的。

                                            1. 简单应用

                                            最简单的mixin由mixin & with关键字组成。

                                            ‘教师‘ 一种能力是 ‘绘画’

                                            void main() {
                                              Teacher().draw();
                                            }
                                            mixin DrawFunc {
                                              String content = '..';
                                              String what();
                                                
                                              void draw() {
                                                print('I can draw ${what()}');  
                                              }
                                            }
                                            class Teacher with DrawFunc {
                                              String what() => "car";
                                            }
                                            
                                            1. 限定类型(mixin…on)

                                            我们在mixin上使用了on关键字,那么mixin只能在那个类的子类上使用,而mixin可以调用那个类的方法。

                                            限定 ‘绘画’ 这种能力只能够用在 ‘人类’ 上面

                                            void main() {
                                              Teacher().draw();
                                            }
                                            class Person {}
                                            mixin DrawFunc on Person {
                                              String content = '..';
                                              String what();
                                                
                                              void draw() {
                                                print('I can draw ${what()}');  
                                              }
                                            }
                                            class Teacher extends Person with DrawFunc {
                                              String what() => "car";
                                            }
                                            
                                            1. 多个类型

                                            在 ‘绘画’ 的基础上,我们增加一种新的能力 ‘唱歌’

                                            void main() {
                                              Teacher().draw();
                                              Teacher().sing();
                                            }
                                            class Person {}
                                            mixin DrawFunc on Person {
                                              String content = '..';
                                              String what();
                                              void draw() {
                                                print('I can draw ${what()}');  
                                              }
                                            }
                                            mixin SingFunc on Person {
                                              void sing() {
                                                print('I can sing');
                                              }
                                            }
                                            class Teacher extends Person with DrawFunc, SingFunc {
                                              String what() => "car";
                                            }
                                            
                                            1. 组合组块
                                            • mixin:定义了组块。
                                            • on:限定了使用mixin组块的宿主必须要继承于某个特定的类;在mixin中可以访问到该特定类的成员和方法。
                                            • with:负责组合组块,而with后面,这一点需要注意,例如下面这样:
                                              void main() {
                                                Teacher().draw();
                                                Teacher().sing();
                                                Teacher().dance();
                                              }
                                              class Person {}
                                              mixin DrawFunc on Person {
                                                
                                                String content = '..';
                                                
                                                String what();
                                                  
                                                void draw() {
                                                  print('I can draw ${what()}');  
                                                }
                                              }
                                              mixin SingFunc on Person {
                                                void sing() {
                                                  print('I can sing');
                                                }
                                              }
                                              abstract class DanceFunc {
                                                void dance() {
                                                  print('I can dance');
                                                }
                                              }
                                              class Teacher extends Person with DrawFunc, SingFunc, DanceFunc {
                                                String what() => "car";
                                              }
                                              

                                              总结就是,mixin可以理解为一个个的功能组块,哪些宿主需要哪些功能就with到上去。

                                              on关键字一方面是为了限制组块的应用场景,也可以为多个组块提供公共的基础功能。

                                              空安全 Null safety

                                              • 空安全的目的是让开发人员对代码中的 Null 可见且可控,并且确保它不会传递至某些位置从而引发崩溃。相关关键字有以下这些:
                                                • ?
                                                • !
                                                • late

                                                  如果可以为空值的变量(null), 在类型声明处加上 ?。

                                                  String? name = null;
                                                  

                                                  在您已经明确一个非空变量一定会在使用前初始化,而 Dart 分析器仍然无法明确的情况下,您可以在变量的类型前加上late。

                                                  void main() {
                                                    late TextEditingController textEditingController;
                                                    init() {
                                                      textEditingController = TextEditingController();
                                                    }
                                                  }
                                                  

                                                  当您正在调用一个可空的变量或者表达式时,请确保您自己处理了空值。例如:您可以使用 if 条件句、?? 操作符 或是 ?. 操作符来处理可能为空的值。

                                                  // 使用 ?? 操作符来避免将非空变量赋予空值
                                                  Cat cat = Cat();
                                                  String name = cat.name ?? "果果";
                                                  

                                                  如果您能确定一条可空的表达式不为空,您可以在其后添加 ! 让 Dart 处理为非空。

                                                    Cat cat = Cat();
                                                    cat.name = "果果";
                                                    String name = cat.name!;
                                                  

                                                  一旦您开始使用空安全,当操作对象可能为空时,您将不再能使用成员访问符(.),取而代之的是可空版本的?.

                                                    Cat? cat;
                                                    String? name = cat?.name;
                                                  

                                                  Dart异步原理

                                                  Dart 是一门单线程编程语言。异步 IO + 事件循环,Dart异步主要可以通过以下关键字来实现:

                                                  • Future
                                                  • async
                                                  • await

                                                    Future 对象封装了Dart 的异步操作,它有未完成(uncompleted)和已完成(completed)两种状态。completed 状态也有两种:一种是代表操作成功,返回结果;另一种代表操作失败,返回错误。

                                                    Future fetchUserName() {
                                                      //想象这是个耗时的获取用户名称操作
                                                      return Future(() => '果果');
                                                    }
                                                    void main() {
                                                      fetchUserName().then((result){print(result)})
                                                      print('after fetch user name ...');
                                                    }
                                                    

                                                    通过.then来回调成功结果,main会先于Future里面的操作,输出结果:

                                                    flutter: after fetch user name ...
                                                    flutter: 果果
                                                    

                                                    那如果我们想要先打印名称咋办,换一下掉用方式

                                                    Future fetchUserName() {
                                                      //想象这是个耗时的获取用户名称操作
                                                      return Future(() => '果果');
                                                    }
                                                    void main() {
                                                      fetchUserName().then((result){
                                                      print(result); 
                                                      print('after fetch user name ...');
                                                     	 }
                                                      )
                                                    }
                                                    

                                                    输出结果:

                                                    flutter: 果果
                                                    flutter: after fetch user name ...
                                                    

                                                    Future 同名构造器是 factory Future(FutureOr computation()),它的函数参数返回值为 FutureOr 类型,我们发现还有很多 Future 中的方法比如Future.then、Future.microtask 的参数类型也是 FutureOr,这个对象其实是个特殊的类型,它没有类成员,不能实例化,也不可以继承,只是一个语法糖。

                                                    abstract class FutureOr {
                                                      FutureOr._() {
                                                        throw new UnsupportedError("FutureOr can't be instantiated");
                                                      }
                                                    }
                                                    

                                                    想象一个这样的场景:

                                                    • 调用登录接口;
                                                    • 根据登录接口返回的token获取用户信息;
                                                    • 缓存用户信息到本机。
                                                      Future login(String name,String password){
                                                        //登录
                                                      }
                                                      Future fetchUserInfo(String token){
                                                        //获取用户信息
                                                      }
                                                      Future saveUserInfo(User user){
                                                        // 保存用户信息
                                                      }
                                                      

                                                      用 Future 可以这样写:

                                                      login('name','password')
                                                        .then((token) => fetchUserInfo(token))
                                                        .then((user) => saveUserInfo(user));
                                                      

                                                      但是这种看着有点别扭,所以我们可以换成关键字处理,换成async和await则可以这样:

                                                      void doLogin() async {
                                                        String token = await login('name','password'); //await 必须在 async 函数体内
                                                        
                                                        User user = await fetchUserInfo(token);
                                                        
                                                        await saveUserInfo(user);
                                                        
                                                      }
                                                      

                                                      需要注意的是如果声明了 async 的函数,返回值是必须是 Future 对象。即便你在 async 函数里面直接返回 T 类型数据,编译器会自动帮你包装成 Future 类型的对象,如果是 void 函数,则返回 Future 对象。在遇到 await 的时候,又会把 Futrue 类型拆包,又会原来的数据类型暴露出来,所以请注意,await 所在的函数必须添加 async 关键词。

                                                      await 的代码发生异常,捕获方式跟同步调用函数一样:

                                                      void doLogin() async {
                                                        try {
                                                          var token = await login('name','password');
                                                          var user = await fetchUserInfo(token);
                                                          await saveUserInfo(user);
                                                        } catch (err) {
                                                          print('Caught error: $err');
                                                        }
                                                      }
                                                      

                                                      语法糖

                                                      Future getUserInfo() async {
                                                        return 'aaa';
                                                      }
                                                      //等价于:
                                                      Future getUserInfo() async {
                                                        return Future.value('aaa');
                                                      }
                                                      

                                                      Completer

                                                      在Flutter中,Completer是一个类,用于实现异步操作的等待和结果处理。Completer允许您创建一个Future对象,并在该对象的值(或错误)可用时解决该对象。

                                                      Completer对象包含两个主要方法:complete()和completeError()。complete()方法将Future对象标记为已完成,并将其结果设置为指定的值,而completeError()方法将Future对象标记为已完成,并将其结果设置为指定的错误。使用Completer时,您可以通过Future对象的then()方法或await关键字来等待异步操作的结果。

                                                      以下是一个示例,演示如何使用Completer来处理异步操作的结果:

                                                      Completer completer = Completer();
                                                      // 假设在两秒钟后异步返回一个值
                                                      Future.delayed(Duration(seconds: 2), () {
                                                        completer.complete(42);
                                                      });
                                                      // 使用then()方法等待异步操作的结果
                                                      completer.future.then((value) {
                                                        print('异步操作的结果为:$value');
                                                      });
                                                      

                                                      在上面的示例中,创建了一个Completer对象,并通过Future.delayed()方法模拟一个异步操作,该操作在两秒钟后返回一个值。然后,使用then()方法等待异步操作的结果,并在结果可用时打印该结果。

                                                      Completer是Flutter中处理异步操作的重要工具之一,特别是在需要处理多个异步操作的情况下,Completer可以更好地控制异步操作的执行顺序和结果处理。

                                                      Isolate

                                                      在Flutter中,Isolate是一种轻量级的、独立的执行线程,它与主线程(也称为UI线程)并行运行,并可以执行CPU密集型任务,而不会阻塞UI线程。Flutter中的每个Isolate都有自己的内存空间,可以独立于其他Isolate进行操作。

                                                      Isolate可以在Flutter应用程序中实现并发性,可以将一些耗时的任务(如网络请求、文件操作、复杂计算等)分配给Isolate,从而使UI线程不会被阻塞,从而提高应用程序的性能和响应速度。

                                                      Flutter中可以通过使用compute()函数或Isolate.spawn()方法来创建和使用Isolate。compute()函数是Flutter提供的一个方便的API,它允许您在后台Isolate中执行耗时的计算,并在完成后返回结果。例如,以下代码演示了如何使用compute()函数来计算斐波那契数列的第20项:

                                                      int fibonacci(int n) {
                                                        if (n 

免责声明
本网站所收集的部分公开资料来源于AI生成和互联网,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复: 表情:
评论列表 (暂无评论,人围观)

还没有评论,来说两句吧...

目录[+]