Flutter学习

张开发
2026/4/18 0:37:41 15 分钟阅读

分享文章

Flutter学习
变量声明Dart中的变量声明-var关键字var语法var 变量名值/表达式注意使用var声明的变量其类型在第一次赋值之后确定不能再赋值其他类型的值void main(){ var age 28; // 使用var关键字声明 print(age); age 21; print(age); // 年龄发生变化 }Dart中的常量声明-const场景当做圆形计算的时候n的值一开始就是被确定的且不允许更改使用const进行声明关键字const语法const 属性名值/表达式特点const是代码编译前被确定不允许表达式中有变量存在必须为常量或者固定值Dart中的常量声明-final场景当我们需要当前时间作为当前唯一的操作时间时间一旦被确定就不可以被修改。关键字final语法final属性名值/表达式特点final变量在运行时被初始化其值设置后不可更改void main(ListString args) { final time DateTime.now(); print(time); }总结变量当需要存储一个变化的数据需要使用var来声明变量编译时常量当需要存储一个不变的数据且在编译时就确定需要使用const声明常量运行时常量当需要存储一个不变的数据但是在运行时才确定需要使用final声明常量数据类型字符串-StringDart中的常用类型-String-模板字符串场景当String类型的变量当前时间来显示可以使用模板字符串或者拼接实现。需求打印出我要在(具体时间)的时候吃早饭语法string 属性名文本内容$变量名或 String 变量名文本内容${变量名}注意当存在模板中的内容是一个表达式的时候需要使用${},更推荐使用${}void main(ListString args) { String text我要在${DateTime.now()}吃早饭; print(text); }数字类型-int/num/doubleDart中的数字类型-int/num/double场景当我们需要描述一个数字类型的时候需要使用int/num/double区别int-整型数字num-可整型可小数double-小数语法int/num/double 属性名数值;Dart中的数字类型-赋值关系注意:数字之间的赋值关系double和int不能直接赋值num不能直接给double赋值double可直接给num赋值void main(ListString args) { int friendCount 3;// 我有几个朋友 print(我有$friendcount个朋友); double appleCount 3.4;// 我买了3.4斤苹果 print(我买了$applecount斤苹果); num rest 1.5;// 我有几个月的假期 print(我今年有$rest月的假期); //friendCount appleCount;// int和double不允许直接赋值 friendCount appleCount.toInt();// int和double 转化之后可以赋值 appleCount friendcount.toDouble(); rest appleCount;// double可以直接给num赋值 appleCount rest.toDouble();// num给double赋值需要转化 }布尔类型-boolDart中的布尔类型-bool场景当我们需要一个属性来表示当前为真(true)或假(false)的时候需要使用bool关键字声需求声明当前自己是否已经完成作业语法bool属性名true/false;void main(Liststring args){ bool isFinishWork false; print(我完成作业的状态为$isFinishWork); }列表类型-ListDart中的列表类型-List场景当一个变量需要存储多个值的时候可以使用列表类型List需求一个班级的学生用List存储支持对学生的查找、新增、删除、循环语法List 属性名 [学生1’学生2];Dart中的列表类型-List的常用操作方法在尾部添加-add(内容)在尾部添加一个列表-addAl(列表)删除满足内容的第一个-remove(内容)删除最后一个-removeLast()删除索引范围内数据-removeRange(start,end)注意:end不包含在删除范围内void main(Liststring args){ List students [张三李四王五]; students.add(新同学);// 在尾部添加 //在尾部添加一个数组 students.addAll([ 新班的同学1 新班的同学2 ]); //删除满足内容的第一个 students.remove(新同学); // 删除最后一个 students.removeLast(); // 删除索引范国内的数据 students.removeRange(0,2); }Dart中的列表类型-List的常用操作方法和属性循环-forEach((item){})是否都满足条件-every((item){return 布尔值 })筛选出满足条件的数据-where((item){return 布尔值});列表的长度(属性)-length最后一个元素(属性)-last第一个元素(属性)-first是否为空(属性)-isEmptyvoid main(Liststring args){ List students [张三李四王五]; students.forEach((item){ print(iten); }; // 是否都满足条件 print(students.every((item){ return item.tostring().startswith(新); })); // 筛选出所有满足条件的数据 print(students.where((item){ return item.tostring().startswith(新); }.toList()); // 列表的长度 print(students.length); // 最后一个元素 print(students.last); // 第一个元素 print(students.first); // 是否为空列表 print(students,isEmpty); }字典类型-MapDart中的字典类型-Map场景当存储的英文需要找到对应的中文描述需要使用键值对类型Map需求需要定义一个英文对应中文的描述并可以通过英文找到对应的中文语法1Map 属性名 {key: value };语法2字典[key]可以取值和赋值void main(Liststring args){ Map transMap {lunch:午饭,morning:早上,hello:你好}; print(transMap[hello]); transMap[hello]你非常好; print(transMap[hello]); }Dart中的字典类型-Map的常用操作方法循环-forEach在添加一个字典-addAll是否包含某个key-containsKey删除某个key-remove清空-clearvoid main(Liststring args){ Map transMap {lunch:午饭,morning:早上,hello:你好}; // 循环 transMap.forEach((key, value){ print($key,$value); }; // 添加一个字典 transMap.addAll({fine:很好}); // 是否包含某个key transMap.containsKey(fine); // 删除某个key transMap.remove(fine); // 清空字典 transMap.clear(); }动态类型-dynamicDart中的动态类型-dynamic定义Dart语言中dynamic用来声明动态类型特点允许变量运行时自由改变类型同时绕过编译时的静态检查语法dynamic 属性名值Dart中的动态类型-dynamic和var的区别dynamic运行时可自由改变类型无编译检查方法和属性直接调用var根据初始值进行推断类型确定类型后类型确定有编译检查仅限推断的属性和方法void main(ListString args){ // 自由设置类型 var text 1; text.toDouble(); dynamic text1 1; text1.startswith();// 虽然运行报错但是绕过编译不会提示 }空安全机制Dart中的空安全机制定义在Dart语言中通过编译静态检查将运行时空指针提前暴露特点将空指针异常从运行时提前至编译时减少线上崩溃常用空安全操作符操作符符号作用示例可空类型?声明可空变量String? → 允许 String或 null安全访问?.对象为 null时跳过操作返回 nulluser?.name → 若 user为 null则返回 null非空断言!.开发者保证变量非空(否则运行时崩溃)name!.length → 断言 name非空空合并??左侧为 nul时返回右侧默认值name??Guest → name为 null时返回Guest运算符算术运算符Dart中的常见算术运算符定义:在Dart语言中对数字进行加减乘除运算采用算术运算符运算符作用加-减*乘/除~/整除%取余数void main(ListString args){ double item 10.99;// 商品单价 double allPrice item *4; // 乘法 double money 100; double lastMoney money - allPrice; // 减法 // double everyHoney lastMoney / 4; // 除法 int everyHoney lastMoney ~/4; // 整除 // int everyMoney 10 % 4; // 取余致 print(everyMoney); }赋值运算符Dart中的常见赋值运算符定义在Dart语言中对数据进行赋值运算采用赋值运算符运算符作用赋值操作加等a b 相等于 a a b-减等a - b 相等于 a a - b*乘等a * b 相等于 a a * b/除等a / b 相等于 a a / bvoid main(ListString args){ double a 1; a 2; print(a); a - 1; print(a); a * 2; print(a); a / 2; print(a); }比较运算符Dart中的常见比较运算符定义在Dart语言中对数值进行比较操作实用比较运算符特点比较运算符的结果都是布尔类型运算符作用判断两个值是否相等!判断两个值是否不等判断左侧值是否大于右侧值判断左侧值是否大于等于右侧值判断左侧值是否小于右侧值判断左侧值是否小于等于右侧值逻辑运算符Dart中的逻辑运算符定义在Dart语言中需要对于bool类型的值进行逻辑运算需要使用逻辑运算符运算符作用逻辑与a b,a和b同时true得true||逻辑或allba和b有一个true得true逻辑非la对a变量进行取反注意:使用逻辑运算符必须保证参与的变量为布尔类型函数函数的定义Dart中的函数定义定义在Dart语言中函数是代码组合和复用的核心单元场景应用程序中很多地方需要做两数之和的运算可以定义函数来组织代码// 返回类型、函数名、参数、函数体 int add (int a, int b){ return a b; }Dart中的函数的返回值分类函数返回值分为有返回值和无返回值有返回值具体类型 函数名称(){}无返回值 void 函数名称(){}注意返回值类型可省略Dart会自动推断类型为dynamic推荐虽然返回值可省略明确返回值类型是更推荐的编程习惯// 带返回值 int add(int a, int b){ return a b; } // 无返回值 void test() { print(”测试无返回值”); } // 无明确类型自动推断 getValue(){ return 1 2; }必传参数、可选位置参数函数的参数-必传参数分类函数的参数分为必传参数可选位置参数可选命名参数特点必传参数不能为空void main(Listestring args){ // 必传参数 add(1,2); } int add(int a, int b) return a b; }函数的参数-可选位置参数特点可选位置参数必须位于必传参数后面采用中括号包裹语法函数名(String a,[String?b,….])传递时按照顺序传递适用场景参数少且顺序固定时默认值可选参数可以设置默认值void main(Liststring args){ print(combine(1)); } String combine(String a,[string? bb,string? c c]){ return a (b ?? 默认值b)(c ?? 默认值c); }可选命名参数函数的参数-可选命名参数特点可选命名参数必须位于必传参数后面采用大括号包裹语法函数名(String a,{String?b,..})传递时按照 参数名:值的方式进行传递无需关注顺序适用场景参数多且需明确含义时默认值可选参数可以设置默认值void main(ListString args){ showPerson(张三); } void showPerson(String username,{int? age 10,String? sex男}){ print(姓名:$username年龄:$age性别:$sex); }类-classDart中的类-class定义Dart语言中类(class)是面向对象编程的核心类包含属性和方法来定义对象的行为和状态需求定义一个Person类属性包括姓名、年龄、性别包括学习的方法定义类语法class Person {属性 方法 }实例化对象Person 变量 Person();属性和方法变量.属性/方法()void main(ListString args){ // 实例化类 Person p Person(); // Person p new Person(); 新版的Dart可以忽略new p.name 老高; p.age 35; p.study(); } // 定义类 class Person{ String name ; int age 0; String sex 男; void study(){ print($name在学习); } }构造函数-默认构造函数Dart中类的构造函数-默认构造函数定义实例化对象的时候使用构造函数直接给对象中的属性赋值常见分类:默认构造函数、命名构造函数、构造函数的语法糖定义语法class 类名{类名(可选命名参数){}}实例化语法:Person pnew Person(属性: 值)vold main(ListString args){ Person p Person(name:张二); p.study(); } class Person { String? name; int? age; String? sex; Person({String? name, int? age,String? sex}){ this.name name; this.age age; this.sex sex; } void study(){ print($nane在学习); } }构造函数-命名构造函数定义构造函数可以采用命名的方式返回一个实例化对象定义语法class 类名 {类名.构造函数名(可选命名参数){}}实例化语法Person pPerson.构造函数名(属性:值)注意默认构造函数和命名构造函数可同时存在vold main(ListString args){ Person p Person.createPerson(name:张三); p.study(); } class Person { String? name; int? age; String? sex; // 命名构造函数 Person.createPerson({String? nane, int? age, String? sex}){ this.name name; this.age age; this.sex sex; } void study(){ print($name在学习); } }构造函数-构造函数语法糖定义同名构造函数和命名构造函数都支持简写写法语法class 类名{类名({ this.属性1this.属性2 });或类名.命名函数({ this.属性1this.属性2 });}void main(ListString args){ Person p Person.createPerson(name:张三); p.study(); Person pp Person(name:张三); pp.study(); } class Person{ String? name; int? age; String? sex; // 命名构造函数 Person({this.name,this.age,this.sex}); // 简写 Person.createPerson({this.name,this.age,this.sex}); // 命名函数简写 void study(){ print($name在学习); } }类的公有属性和私有属性Dart中类的公有属性和私有属性公有属性提供自身或者其他外部文件和类使用的属性和方法私有属性仅供自身使用的属性和方法其他外部文件和类无法访问语法私有属性以下划线开头如_name其余均为公有属性// person.dart 文件 class Person { String? _name; int? _age; String? _sex; // 命名构造函数 Person.createPerson({string? name, int? age, string? sex}){ this._name name; this._age age; this._sex sex; } void study(){ print($_name在学习); } } // main.dart 文件 void main(ListString args){ Person p Person.createPerson(name:张三); p._name ; // 私有属性无法被调用 }类的继承Dart中类的继承定义继承是拥有父类的属性和方法特点dart属于单继承一个类只能拥有一个直接父类子类拥有父类所有的属性和方法语法class 类名 extends 父类重写子类可通过override注解重写父类方法扩展其行为注意子类不会继承父类构造函数子类必须通过super关键字调用父类构造函数确保父类正确初始化super语法子类构造函数(可选命名参数):super({参数))class Parent { String? name; int? age; Parent({this.name,this.age}); void study(){ print($name父类学习); } } class Child extends Parent { Child({String? name, int? age}) : super(name: name, age:age); //重写方法 override void study() { // super.study(); // 调用了父类的方法 print($name子类学习); } } void main(ListString args){ Child c Child(name:张三, age: 18); c.study(); }类的多态Dart中类的多态-继承和方法重写定义Dart中的类的是指同一操作作用于不同的对象可以产生不同的执行效果场景微信和支付宝都遵循同样支付接口但实现逻辑不同即同一个支付操作拥有不同的支付效果实现方式1.继承和方法重写、2.抽象类和接口需求定义一个父类分别实现微信和支付宝支付类重写得到不同的支付逻辑// 声明基础支付类 class PayBase { pay(){ print(基础支付); } } // 微信支付类 class WxPay extends PayBase{ override pay(){ print(“微信支付”); } } // 支付宝支付类 class AliPay extends PayBase { override pay(){ print(支付宝支付); } } // 调用支付 void main(ListString args) { PayBase p WxPay(); p.pay(); }Dart中类的多态-抽象类和接口实现方式使用abstract关键字声明一个抽象类(没有实现体)方式使用implements关键字继承并实现抽象类// 定义抽象类 abstract class PayBase { void pay(); // 抽象类是不写具体实现的 } // 微信支付类 class WxPay implements PayBase { override void pay(){ print(微信支付); } } // 支付宝支付类 class AliPay implements PayBase { override void pay(){ print(支付宝支付); } } void main(ListString args) { PayBase p WxPay(); p.pay(); }类的混入Dart中类的混入定义Dart允许在不使用传统继承的情况下向类中添加新的功能方式使用mixin关键字定义一个对象方式使用with关键字将定义的对象混入到当前对象特点一个类支持with多个mixin调用优先级遵循“后来居上”原则即后混入的会覆盖先混入的同名方法需求让一个学生类和一个老师类都拥有唱歌的方法// 定义混入对象 mixin Base { void song(String name){ print($name我会唱歌); } } // 混入Base对象 class Student with Base { String? name; int? age; Student({this.name, this.age)); } class Teacher with Base { String? name; int? age; Teacher({this.name, this.age}); } void main(ListString args){ Student s Student(name:小高同学); s.song(s.name!); Teacher t Teacher(name:老张老师”); t.song(t.name!); }泛型Dart中泛型定义Dart允许使用类型参数限定类型的同时又让类型更加灵活让代码更加健壮和维护性更强场景List类型中只想存储String类型怎么办?函数中返回值希望和参数一个类型怎么办?常见分类泛型集合、泛型方法、泛型类// 定义一个泛型List ListString list []; list.add(张三); list.add(李四); list.add(王五); print(list); // 定义一个泛型方法 void printListT(ListT list){ for (var i0;ilist.length; i){ print(list[i]); } } // 泛型 class StudentT{ T? name; int? age; Student({this.name, this.age)); }异步编程事件循环Future启动文件说明-runApp和Widget基础组件MaterialAppScaffold组件自定义组件Flutter自定义组件-无状态组件和有状态组件定义根据自己特定的需求创建自己的widget分类Flutter分为无状态组件和有状态组件特性StatelessWidget(无状态)StatefulWidget(有状态)核心特征一旦创建内部状态不可变持有可在其生命周期内改变的状态使用场景静态内容展示外观仅由配置参数决定交互式组件如计数器、可切换开关、表单输入框生命周期相对简单主要是构建(build)更为复杂包含状态创建、更新和销毁代码结构单个类两个关联的类:widget 本身和单独的 State 类无状态组件-StatelessWidget定义创建一个新的类继承Statelesswidget类并实现build方法要点build返回一个Widget场景纯展示型组件没有用户交互操作案例加载更多组件isLoading 和 hasMore这两个变量不是在 load_more.dart 内部改变的它们是从父页面传进来的父页面通过setState更新 → 自动传给子组件子组件只需要展示不需要自己管理状态。import package:flutter/material.dart; class LoadMore extends StatelessWidget { const LoadMore({Key? key, required this.isLoading, required this.hasMore}) : super(key: key); final bool isLoading; // 是否正在加载 final bool hasMore; // 是否还有更多数据 override Widget build(BuildContext context) { // 没有更多数据 if (!hasMore) { return const SizedBox( height: 60, child: Center( child: Text( 没有更多数据了, style: TextStyle(fontSize: 12, color: Color(0xFF999999)), ), ), ); } // 正在加载 if (isLoading) { return const SizedBox( height: 60, child: Center(child: CircularProgressIndicator(strokeWidth: 2)), ); } // 默认占位 return const SizedBox(height: 20); } }有状态组件-StatefulWidget组件生命周期生命周期一、初始化阶段页面出生1.constructor构造方法最先执行作用接收父组件传过来的参数此时还没上下文context不能调用 setState2.initState()生命周期第一个方法只执行1 次作用初始化变量、控制器发送网络请求监听事件可以用context可以setState二、构建 / 更新阶段页面显示 刷新3.didChangeDependencies()在initState之后执行可能执行多次场景依赖InheritedWidget主题、语言、上下文变化4.build()最核心、最熟悉渲染 UI调用setState就会重新执行不要在这里写耗时逻辑三、销毁阶段页面死亡5.dispose()页面销毁最后执行只执行 1 次必须在这里关闭控制器TextEditingController取消流监听销毁动画取消定时器✅ 记住不写 dispose 会内存泄漏额外 2 个常用生命周期进阶但必须知道6.didUpdateWidget()父组件刷新 → 当前组件被重建时调用初学者很少用到7.deactivate()/activate()页面切后台 / 切回来时调用类似 Android 的 onPause /onResume执行顺序1. constructor 构造方法 2. initState() ← 初始化 3. didChangeDependencies() 4. build() ← 渲染UI ------------------------ 5. didUpdateWidget() ← 父组件刷新 6. build() ← 重新渲染 ------------------------ 7. deactivate() ← 页面离开 8. dispose() ← 销毁必写import package:flutter/material.dart; void main() runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); override Widget build(BuildContext context) { return MaterialApp( home: const LifeCyclePage(), ); } } class LifeCyclePage extends StatefulWidget { const LifeCyclePage({super.key}); override StateLifeCyclePage createState() _LifeCyclePageState(); } class _LifeCyclePageState extends StateLifeCyclePage { // 1. 构造方法 _LifeCyclePageState() { print(✅ 1. 构造方法执行); } // 2. 初始化 override void initState() { super.initState(); print(✅ 2. initState 执行); } // 3. 依赖变化 override void didChangeDependencies() { super.didChangeDependencies(); print(✅ 3. didChangeDependencies 执行); } // 4. 渲染UI override Widget build(BuildContext context) { print(✅ 4. build 执行); return Scaffold( appBar: AppBar(title: const Text(生命周期测试)), body: Center( child: ElevatedButton( onPressed: () { setState(() {}); // 点击刷新看 build 重复执行 }, child: const Text(点我刷新), ), ), ); } // 5. 页面销毁 override void dispose() { print(✅ 8. dispose 执行); super.dispose(); } }事件布局组件基础容器-Container基础容器-Center基础容器-Align基础容器-Padding线性布局-Column线性布局-Row弹性布局-Flex作用:允许沿一个主轴(水平或垂直)排列其子组件灵活地控制这些子组件在主轴上的尺寸比例和空间分配属性类型作用说明directionAxis.horizontal/Axis.vertical主轴方向决定子组件的排列方向mainAxisAlignmentMainAxisAlignment子组件在主轴方向上的对齐方式。crossAxisAlignmentCrossAxisAlignment子组件在交叉轴方向上的对齐方式mainAxisSizeMainAxisSizeFlex 容器自身在主轴上的尺寸策略子组件:Flex的子组件常使用Expanded或Flexible来控制空间分配Flex是Column和Row的结合体弹性布局-Flex/Expanded/FlexibleExpanded/Flexible作为Flex的子组件通过flex属性来分配Flex组件空间import package:flutter/material.dart; class FlexPage extends StatelessWidget { const FlexPage({super.key}); override Widget build(BuildContext context) { return Container( color: Colors.orange, child: Flex( direction: Axis.horizontal, children: [ Expanded(flex: 2, child: Container(color: Colors.red)), Expanded(flex: 1, child: Container(color: Colors.green)), ], ), ); } }运行效果如图Flex布局受其父组件传递的约束影响。确保父组件提供了适当的布局约束Expanded与 Flexible 的区别: Expanded强制子组件填满所有剩余空间,Flexible根据自身大小调整,不强制占满空间流式布局-Wrap层叠布局-Stack/Positioned文本组件-Text图片组件-Image文本输入组件-TextField作用实现文本输入功能的核心组件属性作用说明controller编辑框的控制器通过它可以设置/获取编辑框的内容、选择编辑内容、监听编辑文本改变事件decoration用于控制TextField的外观显示如提示文本、背景颜色、边框等style定义输入文本的样式textAlign输入框内编辑文本在水平方向的对齐方式。maxLines最大行数maxLengthmaxLength代表输入框文本的最大长度设置后输入框右下角会显示输入的文本计数。maxLengthEnforcementmaxLengthEnforcement决定当输入文本长度超过maxLength时如何处理如截断、超出等。obscureText是否隐藏正在编辑的文本如用于输入密码的场景等文本内容会用“•”替换。autofocus是否自动获取焦点。toolbarOptions长按或鼠标右击时出现的菜单包括 copy、cut、paste 以及 selectAll。enable如果为false则输入框会被禁用禁用状态不能响应输入和事件同时显示禁用态样式在其decoration中定义。onChanged输入内容发生变化时执行的回调函数onSubmitted用户提交输入时的回调函数override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text( 登录, style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold), ), backgroundColor: Colors.white, ), body: Container( padding: EdgeInsets.all(20), child: Column( children: [ TextField( controller: _phoneController, maxLength: 11, decoration: InputDecoration( labelText: 手机号, hintText: 请输入手机号, prefixIcon: Icon(Icons.mobile_friendly), ), onChanged: (v) { print(手机号onChange: $v); }, ), SizedBox(height: 20), TextField( obscureText: true, decoration: InputDecoration( labelText: 密码, hintText: 请输入密码, prefixIcon: Icon(Icons.lock), ), ), SizedBox(height: 20), ElevatedButton( onPressed: () { print(登录: ${_phoneController.text}); }, child: Text(登录), ), ], ), ), ); }常用滚动组件组件特点使用场景SinglechildScrollView让单个子组件可以用滚动所有内容一次性渲染长表单、设置页、内容不固定但是总量不多的页面ListView线性列表通过builder可以实现懒加载性能优异聊天记录、新闻、常见的单列滚动的数据列表Gridview网格布局列表支持懒加载可以固定列数图片墙、商品网格、应用图标列表CustomScrollView复杂布局方案通过组合多个编辑组件实现滚动电商首页、社交APD个人主页多个滚动紧密联动PageView整页滚动效果支持横向和纵向应用引导页、图片轮播图、书籍翻页SingleChildScrollView常用滚动组件-SingleChildScroll用法:包裹一个子组件让单个子组件具备滚动能力。ListViewGridViewCustomScrollViewSliverGrid、SliverList 只能纵向排列PageView组件通信组件通信-父传子组件通信-子传父网络请求-Dio插件使用路由管理路由跳转方法方法核心作用使用场景典型场景pushNamed进入新页面[A,B]→ [A, B, C]常规页面跳转如列表页进入详情页pushReplacementNamed替换当前页面[A, B]→ [A, C]登录成功后跳转主页并无法返回登录pushNamedAndRemoveUntil跳转新页面并清理栈[A, B, C, D]→ [A, E]退出登录后跳转登录页并清空所有历史页面popAndPushNamedpopUntil返回并立即跳转新页面[A, B, C]→ [A, B, D]购物车页面结算后返回商品列表并同时跳转到订单页popUntil连续返回直到条件满足[A, B, C, D]→ [A, B]从设置页的深层级一键返回到主设置页面路由传递参数作用通过路由传递参数是实现页面间数据通信的常用方式传递参数(命名路由)Navigator.pushNamed(context, 地址, arguments:{参数})接收参数(命名路由)ModalRoute.of(context)?.settings,arguments接收时机initstate获取不到路由参数放置在Future.microtask(异步微任务)中动态路由与高级控制Getx共享用户数据安装getxflutter pub add get创建项目安装Flutter https://docs.flutter.cn/install/quick搭建项目# 创建项目 flutter create shop # 创建指定平台项目如适配web平台项目 flutter create --platforms web shop_web # 检查项目 flutter doctor # 本地已安装xcode 启动 iOS 模拟器默认机型 open -a Simulator # 查看可用设备 flutter devices # 运行项目 flutter run # 指定模拟器运行当有多个设备时 flutter run -d iPhone 16 Pro # 设备名称需和 flutter devices 输出一致含空格需加引号 # 或用设备 ID 运行更精准 flutter run -d 6E72F8A1-XXXX-XXXX-XXXX-XXXXXXXXXXXX在运行flutter run的终端窗口中直接按下r键小写即可触发热重载页面会快速更新且不会重置当前状态。Flutter命名规范文件夹 / 文件命名小写 下划线work_order/work_order_list.dart类名 / 枚举 / 混入大驼峰class HomePage {} class UserModel {} enum LoadStatus {} mixin LoadMore {}变量 / 方法 / 函数小驼峰String userName; int currentIndex; void getUserInfo() {} Widget buildBanner() {}Flutter常用命令依赖相关flutter pub get # 安装 pubspec.yaml 里的所有插件 flutter pub upgrade # 升级所有插件版本 flutter pub clean # 清理依赖缓存项目运行flutter run # 运行项目默认设备 flutter run -d chrome # 运行在 Chrome 网页 flutter run -d android # 运行在安卓 flutter run -d ios # 运行在苹果打包构建flutter build apk # 打包 Android 正式包 flutter build ios # 打包 iOS 需要 Mac flutter build web # 打包网页版排查 / 修复问题flutter clean # 清理项目缓存解决90%编译报错 flutter pub get # 清理后必执行 flutter doctor # 检查 Flutter 环境是否正常 flutter analyze # 检查代码语法错误/规范设备相关flutter devices # 查看已连接的设备 flutter emulators # 查看模拟器列表帮助 / 版本flutter --version # 查看 Flutter 版本 flutter help # 查看帮助

更多文章