Flutter学习笔记:dart语法 面试必备
2024-11-07 19:55:06 1 举报
AI智能生成
Flutter开发入门必看、Flutter学习笔记、Dart语法、面试、必备、dart
作者其他创作
大纲/内容
(0)网址:https://flutterchina.club/setup-windows/
说明:以下是mac本配置的方式:(与window方式不一样,但是Flutter中文网上给的镜像的方式是错误的,给的mac上配置的方式,特此说明)export PUB_HOSTED_URL=https://pub.flutter-io.cnexport FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
mac
说明:window配置镜像的方式如下。PUB_HOSTED_URL=https://pub.flutter-io.cnFLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
window
同时可以在用户中心和系统中心进行配置环境变量
(1)使用镜像配置环境变量
网址:https://flutter.dev/docs/development/tools/sdk/releases#windows
下载完成之后,进行解压,然后在进行环境变量的配置配置到path路径下。
打开cmd命令,执行以下命令:flutter doctor执行结果可以查看,flutter需要的条件有哪些,哪些还没有安装,都会给你列出来。(如上图)
命令测试
环境变量配置:D:\\install_files\\flutter\\flutter_sdk\\flutter\\bin配置完成之后,现在就可以使用flutter命令了
(2)下载Flutter的SDK
以上所有工作已经完成后打开android studio进行安装Flutter插件,安装成功后,对android studio进行重启然后在创建新项目的时候,就可以创建flutter项目了
(3)安装插件
(4)所有的准备工作已经完成
错误日志如下:Could not determine the dependencies of task ‘:app:compileDebugJavaWithJavac‘.
buildscript { ext.kotlin_version = '1.3.50' repositories {// google()// jcenter() maven { url 'https://maven.aliyun.com/repository/google' } maven { url 'https://maven.aliyun.com/repository/jcenter' } maven { url 'http://maven.aliyun.com/nexus/content/groups/public' } maven { url 'http://download.flutter.io'} } dependencies { classpath 'com.android.tools.build:gradle:4.1.0' classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version\" }}allprojects { repositories {// google()// jcenter() maven { url 'https://maven.aliyun.com/repository/google' } maven { url 'https://maven.aliyun.com/repository/jcenter' } maven { url 'http://maven.aliyun.com/nexus/content/groups/public' } maven { url 'http://download.flutter.io'} }}rootProject.buildDir = '../build'subprojects { project.buildDir = \"${rootProject.buildDir}/${project.name}\" project.evaluationDependsOn(':app')}task clean(type: Delete) { delete rootProject.buildDir}
解决方法:1、修改android目录下的build.gradle文件中的所有的google()和jcenter()换成阿里云的镜像
buildscript { repositories { maven { url 'https://maven.aliyun.com/repository/google' } maven { url 'https://maven.aliyun.com/repository/jcenter' } maven { url 'http://maven.aliyun.com/nexus/content/groups/public' } } dependencies { classpath 'com.android.tools.build:gradle:3.5.0' }}
解决方法:2、修改flutter sdk下的flutter.gradle文件,具体目录是flutter\\packages\\flutter_tools\\gradle
(5)遇到的第一个问题
Flutter配置开发环境
环境搭建
在dart语言中:变量是一个引用,未初始化的变量值是null;
例如int:abstract class int extends num
int是一个类所有的基本类型都是一个class类,是与java中不同的;
例如:var j = \"yulinmufeng\";j=100;(报错)var l;j = \"yulinmufeng\";j=100;
var 在声明的变量赋值那一刻,就决定了它是什么类型
常量修饰符的区别:dynamic与var的使用方法是相反的(动态的)。例如以下:dynamic z = \"yulinmufeng\";z= 100;但在实际开发的情况下,动态的声明变量和静态的声明变量,dynamic和var变量定义的在执行效率上,不如var定义的变量;dynamic一般在不确定是什么类型的时候,才会使用dynamic来声明变量;dynamic一般使用频率不是很高;var的缺点是,不能很好一眼就看出来是什么类型;object与java中的表现是一样的;
object和dynamic的区别:【调用方法的类型检查时机】不同,编译时类型检查,运行时类型。
Dart所有的变量皆对象
Object、var与dynamic
final:用法与java中是一样的;
final
const:在赋值之后,是不能再次进行赋值的,与final是一样的;final是运行期常量;const是编译期常量;const比final的运行效率要高;
特性:final i = 1;const j = 1;//因为i是运行时确定,所以不能给编译时候就要确定的变量赋值//const z= i;(不可以)//可以使用另一个编译时确定的变量给它赋值const z=j+1;(这样是可以的)
使用场景:均可以声明一个不可变量的声明
const
final与const的区别
变量
说明:1、通过源码中的注释,可以看出int类型,占用的字节数,要看编译运行的平台,分为4字节或者8字节,但可以认为和java一样,为4个字节;2、dart当中的int,在编码的时候,可以将int当成java的int long来使用,如果我们写的dart代码超过了4个字节,那么dart会将其编译成类似的java当中的long否则编译成java当中的short或者int;3、i.bitlength=占用的字节;4、在使用上和java的方式是一样的;备注:原则上java和Dart语言中的int不能拿到一块进行对比,因为Dart中为class类,而java是基本数据类型;
int
说明:1、如果要表示float类型时,只能使用double来表示;2、Dart中的double和在java中的double在使用方式上是一样的;
double
说明:1、num内置数据类型只有两个int和double;
数据类型:num
说明:1、在声明上与java一样;String str = \"走,一起去搓澡!\";(dart)2、方法String.format(\"&s%d\
字符串类型:String
说明:1、bool来定义布尔类型;2、定义方式:bool b= false;
布尔类型:bool
dart 为什么使用final修饰list 可以调用add方法,而使用const修饰list 不可以调用
数据类型:List
遍历
映射集合:Map
Unicode:Runes
说明:1、(很少用到,作为了解)Symbols标识符,类似C、C++中的宏(但不完全相似)2、定义一个symbolsvar a = #asdfg;a输出的时候就是:symbols使用点一般在switch中使用,其他的使用点就不多;switch(a){ case #A: break; case #sadsad: break;}
标识符:Symbols
说明:java中有8大基本数据类型;Dart中有7大内置类型;
内置类型
说明:1、dart语言中没有java中的instantof,而是需要is来实现;is:属于int类型则命中,判断对象是否是指定的类型。if(index is int){}is!:不属于int类型则命中if,判断对象是否不是指定的类型。if(index is! int){}区别:一个是是否是,一个是是否不是
类型判断操作符:is、is!
说明:将对象转换为指定类型1、Dart语言中不支持java中强制类型转换的方法2、Dart例如:num j = 1;//类型转换,不支持java的转化:(int)强转写法int i = j as int;
类型转换操作符:as
类型判定操作符:判断、转换
=(直接赋值)
说明:1、java保证k后续使用时一定不为nullString k;if(null == k){ k = \"123\";}2、dart语言中,??= 判空赋值符,如果k有值,这句话就当它不存在,如果k没有值就赋值456k ??= \"456\";
??=(空赋值符)
赋值操作符:直接赋值、判空赋值
说明:1、java中的话,就像是建造者是一样的,在每次返回的时候,都是他本身,这样的话就可以一直链式调用;2、dart中级联操作符new Builder()..a()..b();class Builder { void a(){ } void b(){ }}
级联操作符:..
三重字符串:``` ```,样例:```我是三重字符串,或称之为原始字符串```
集合扩展操作符:[...[] ]或者{...{}} 列表和字典的扩展操作符
说明:1、如果expr1不为null,那么就返回expr1,否则就返回expr2例如:String k = \"123\";var v = k ?? \"789\";那么v= 123;如果:k = null;var v = k ?? \"789\";那么v = 789;
expr1 ?? expr2(空合并运算符)
说明:1、跟java中的三目运算符是一样的
三目表达式:condition?expr1:expr2
条件运算符:三目、空合并操作符
说明:1、在正常开发的时候,经常遇到的异常就是空指针异常;但是在dart语言中,可以使用?.来解决这个功能。2、grovy和kotlin语言中都有这个?.此功能。
空值检查操作符:?
操作符
在Dart中,运算符用于执行各种操作,如算术运算、比较运算、位运算、逻辑运算和赋值运算等。Dart支持许多常见的运算符,这些运算符可以应用于不同类型的变量。下面是一些Dart中常见的运算符及其用法:### 算术运算符- `+` 加法- `-` 减法- `*` 乘法- `/` 除法- `~/` 整除(返回商的整数部分)- `%` 取模(返回除法的余数)### 比较运算符- `==` 等于- `!=` 不等于- `>` 大于- `<` 小于- `>=` 大于或等于- `<=` 小于或等于### 位运算符- `&` 按位与- `|` 按位或- `^` 按位异或- `~` 按位取反- `<<` 左移- `>>` 有符号右移- `>>>` 无符号右移### 逻辑运算符- `&&` 逻辑与- `||` 逻辑或- `!` 逻辑非### 赋值运算符- `=` 赋值- `+=` 加等于- `-=` 减等于- `*=` 乘等于- `/=` 除等于- `~/=` 整除等于- `%=` 取模等于- `&=` 按位与等于- `|=` 按位或等于- `^=` 按位异或等于- `<<=` 左移等于- `>>=` 右移等于- `>>>=` 无符号右移等于### 条件(三元)运算符- `condition ? exprIfTrue : exprIfFalse`### 条件(判空返值)运算符- exprlfnull ?? returnDefaultExpr### 条件(判空赋值)运算符- exprlfnull ??= setDefaultExpr### 类型运算符- `is` 检查对象是否是特定类型的实例- `is!` 检查对象是否不是特定类型的实例- `as` 类型转换### 其他运算符- `..` 级联运算符,用于在同一对象上连续调用方法或访问属性### 示例下面是一些Dart运算符的使用示例:```dartvoid main() { int a = 10; int b = 5; // 算术运算符 int sum = a + b; // 加法 int diff = a - b; // 减法 int product = a * b; // 乘法 int quotient = a / b; // 除法 int intQuotient = a ~/ b; // 整除 int remainder = a % b; // 取模 // 比较运算符 bool isEqual = a == b; // 等于 bool isNotEqual = a != b; // 不等于 // 逻辑运算符 bool isBothPositive = (a > 0) && (b > 0); // 逻辑与 bool isAtLeastOnePositive = (a > 0) || (b > 0); // 逻辑或 // 赋值运算符 a += b; // a = a + b; // 条件运算符 String result = (a > b) ? 'a is greater' : 'b is greater or equal'; // 类型运算符 bool isInt = a is int; // 检查a是否是int类型 // 级联运算符 List<int> list = []; list..add(1)..add(2)..add(3); // 连续调用add方法 print('Sum: $sum'); print('Difference: $diff'); print('Product: $product'); print('Quotient: $quotient'); print('Integer Quotient: $intQuotient'); print('Remainder: $remainder'); print('Is Equal: $isEqual'); print('Is Not Equal: $isNotEqual'); print('Is Both Positive: $isBothPositive'); print('Is At Least One Positive: $isAtLeastOnePositive'); print('Result: $result'); print('Is a an int: $isInt'); print('List: $list');}```在使用运算符时,请注意运算符的优先级和结合性。如果需要改变默认的优先级,可以使用括号来明确指定运算的顺序。
运算符
位置参数
- **位置参数**:按照定义顺序传递,必须提供。
- **可选位置参数**:使用方括号 `[]` 包裹,可以选择性提供,通常有默认值。
可选位置参数
- **具名参数**:使用大括号 `{}` 包裹,调用时通过参数名传递值。
具名参数
- **混合参数**:可以结合位置参数和具名参数。
混合参数
详解
分类
子主题
**两者的区别**1. **调用方式**:位置参数按照声明的顺序调用,而具名参数通过参数名称调用。2. **灵活性**:具名参数提供了更大的灵活性,因为可以省略某些参数(如果它们有默认值),或者按照任何顺序传递参数。位置参数则要求必须按照声明的顺序传递所有参数。3. **可读性**:具名参数使得代码更具可读性,特别是在参数较多或参数用途不明确的情况下。通过参数名称,可以更容易地理解每个参数的作用。4. **默认值**:具名参数可以具有默认值,而位置参数通常不具有默认值(尽管可以通过其他方式实现)。需要注意的是,Dart中的可选命名参数和可选位置参数在调用函数时不需要为参数指定值,但可选位置参数并不直接存在。Dart的命名参数可以模拟可选位置参数的行为,通过为它们提供默认值来实现。在定义时,可选命名参数使用`{}`包裹,而位置参数则直接按照顺序列出。最后,Dart还支持将参数标记为`@required`或`required`(具体使用哪个与Dart版本相关),以强制要求调用者在调用函数或方法时提供该参数的值。这可以在使用具名参数时提供额外的参数验证。
具名参数和位置参数的区别
参数
在 Dart 中,默认值只能在具名参数中使用。位置参数是不能声明默认值。
默认参数值
方法对象
=>
说明:1、匿名方法,lambda表达式
匿名方法
实例方法
静态方法
工厂方法
参数列表:构造方法的初始化参数列表,c++中有类似的参数列表
构造方法
重写父类的静态方法
实战
方法
说明:(1)介绍catch的参数;1、dart中和java中的异常抛出不一样;如下:void test(){ throw new Exception(\"你好\
异常
在Dart中,并没有直接声明私有类的方式,因为Dart中的类默认就是公共的,可以被任何其他Dart代码访问。然而,你可以通过命名约定来模拟私有属性和方法的行为。以下是如何在Dart中声明私有属性、私有方法和私有静态方法的示例:### 私有属性私有属性通常使用单个下划线`_`作为前缀。```dartclass MyClass { // 私有属性 String _privateProperty = 'This is private'; // 公共方法用于访问私有属性 String getPrivateProperty() { return _privateProperty; } // 公共方法用于设置私有属性 void setPrivateProperty(String value) { _privateProperty = value; }}```### 私有方法私有方法也使用单个下划线`_`作为前缀。```dartclass MyClass { // 私有方法 void _privateMethod() { print('This is a private method'); } // 公共方法调用私有方法 void callPrivateMethod() { _privateMethod(); }}```### 私有静态方法Dart中并没有直接的方式来声明一个私有静态方法。但你可以通过结合私有方法和静态方法的方式来实现类似的功能。私有静态方法通常用于工具函数或者仅在类内部使用的辅助方法。```dartclass MyClass { // 私有静态方法 static void _privateStaticMethod() { print('This is a private static method'); } // 公共静态方法调用私有静态方法 static void callPrivateStaticMethod() { _privateStaticMethod(); }}```需要注意的是,Dart的私有性是通过命名约定来实现的,而不是通过语言特性强制执行的。这意味着,尽管Dart建议并鼓励使用下划线前缀来表示私有成员,但实际上你仍然可以从类的外部访问这些成员。Dart编译器会发出警告,但不会阻止你这样做。因此,遵守这个命名约定主要是为了保持代码的可读性和维护性,而不是为了提供安全性或强制封装。如果你确实需要更严格的访问控制,你可能需要重新考虑你的设计,或者使用其他语言特性(如封装在另一个类中)来模拟更严格的私有性。但在大多数情况下,Dart的命名约定已经足够满足大多数应用的需求。
在Dart中,你可以通过不使用任何特定的关键字来声明私有属性。Dart遵循一种命名约定,即使用下划线`_`开头的标识符被认为是私有的。这种约定在Dart中被广泛接受并作为私有成员的默认实现方式。例如,下面是如何声明一个私有属性的例子:```dartclass MyClass { // 这是一个私有属性 String _privateProperty; // 这是一个公共方法,可以访问和修改私有属性 void setPrivateProperty(String value) { _privateProperty = value; } // 这是另一个公共方法,可以返回私有属性的值 String getPrivateProperty() { return _privateProperty; }}void main() { var obj = MyClass(); // 设置私有属性的值 obj.setPrivateProperty('Hello'); // 获取私有属性的值 print(obj.getPrivateProperty()); // 输出: Hello // 直接访问私有属性会导致编译错误 // print(obj._privateProperty); // 错误: 私有成员无法直接访问}```在这个例子中,`_privateProperty`是一个私有属性,它只能被`MyClass`类内部的方法访问。尽管Dart没有提供语言级别的访问控制修饰符(如Java中的`private`关键字),但使用下划线前缀的命名约定被广泛接受,并且Dart的编译器和工具链都遵循这一约定。需要注意的是,这种约定并不是强制性的,只是Dart社区的一个共识。如果你尝试从类的外部访问一个以下划线开头的属性或方法,Dart编译器会发出警告,但并不会阻止你这样做。然而,这通常被认为是不好的做法,因为它违反了类的封装原则。此外,Dart还提供了一种名为库私有(library-private)的特性,通过在标识符前使用`_`前缀,并紧跟库名,可以声明只有当前库内部可以访问的属性和方法。例如:```dart// 在同一个Dart文件中String _libraryPrivateProperty;// 在另一个Dart文件中,即使属于同一个库,也无法访问// print(_libraryPrivateProperty); // 错误: 无法访问库私有成员```这种库私有特性提供了更细粒度的访问控制,但通常只在大型库或框架中需要更复杂的封装时使用。对于大多数应用和小型库,使用单个下划线前缀的命名约定就足够了。
类说明:1、私有的类和属性,在dart语言中,表示方式;//包括类的定义 如果使用 _ 开头,意味着这个类就是privateclass Point{ int _x;//使用_开始命名的变量,就是java的private,在外面不可以调用 int y;}
私有:私有属性、私有方法均使用头部下划线命名来声明
命名构造函数
参数初始化列表
重定向构造函数
常量构造函数
说明:在命名构造函数前面其实加一个factory就是工厂构造函数;在工厂的构造方法中,不可以使用thisclass MyObject { String name; // 普通构造函数 MyObject(this.name); // 工厂构造函数 factory MyObject.createInstance(String name) { // 在这里可以进行一些逻辑处理 return MyObject(name); }}void main() { // 使用工厂构造函数创建对象 var obj = MyObject.createInstance(\"Example\"); print(obj.name); // 输出:Example}类似类方法
工厂构造函数
构造函数
说明:每一个实例属性,变量都会有一个隐式的get,非final 还有set方法;
Getter与Setter
操作符重载
说明:1、abstract使用abstract修饰符定义一个抽象类,抽象类中允许出现无方法的方法与java没有什么区别,不可以多继承,可以多实现;在 Dart 中,抽象类(Abstract Class)是一种不能被实例化的类,通常用于定义一组方法的接口,其中的方法可以是抽象的(没有具体实现),也可以包含具体的方法。抽象类可以被其他类继承或实现,从而实现其中定义的抽象方法。以下是一个简单的 Dart 抽象类的示例:dartCopy code// 定义一个抽象类abstract class Animal { // 抽象方法,没有具体实现 void makeSound(); // 具体方法 void sleep() { print(\"Animal is sleeping.\"); }}// 可以被继承,继承抽象类并实现抽象方法class Dog extends Animal { @override void makeSound() { print(\"Dog barks!\"); }}// 可以被实现,实现抽象类并实现抽象方法class Cat implements Animal { @override void makeSound() { print(\"Cat meows!\
在Dart中,抽象类(abstract class)允许你定义一个类的结构,但不完全实现它。抽象类可以包含抽象方法(由`abstract`关键字标记的方法),这些方法在抽象类中没有实现,必须在任何继承该抽象类的非抽象子类中实现。对于抽象类中的方法,以下是一些关键点:1. **抽象方法**:在抽象类中定义的方法,如果标记为`abstract`,则不需要(也不可以)在抽象类本身中提供方法体。这样的方法必须在任何非抽象子类中实现。2. **非抽象方法**:抽象类也可以包含非抽象方法,这些方法在抽象类中有具体的实现。子类可以选择重写这些方法,也可以继承它们的默认实现。3. **子类必须实现所有抽象方法**:任何继承抽象类的非抽象子类都必须实现抽象类中定义的所有抽象方法。如果子类没有实现所有抽象方法,那么它本身也必须被标记为`abstract`。所以,对于你的问题,“抽象类中的方法必须被重写吗?”答案是:抽象方法必须在非抽象子类中被重写,但非抽象方法则不是必需的。以下是一个简单的例子:```dartabstract class Animal { // 抽象方法,必须在子类中实现 abstract void makeSound(); // 非抽象方法,子类可以选择重写或者继承默认实现 void eat() { print('The animal eats.'); }}class Dog extends Animal { // 必须实现从Animal继承来的抽象方法makeSound @override void makeSound() { print('The dog barks.'); } // 可以选择重写eat方法,也可以继承默认实现 @override void eat() { print('The dog eats dog food.'); }}void main() { Dog dog = Dog(); dog.makeSound(); // 输出: The dog barks. dog.eat(); // 输出: The dog eats dog food.}```在这个例子中,`Animal`是一个抽象类,它有一个抽象方法`makeSound`和一个非抽象方法`eat`。`Dog`类继承了`Animal`类,并且实现了`makeSound`方法。同时,它也重写了`eat`方法,但如果不重写,它将继承`Animal`类中`eat`方法的默认实现。
抽象方法必须在非抽象子类中被重写,但非抽象方法则不是必需的。】
不需要全部实现
非抽象方法
抽象子类
需要全部实现
非抽象子类
抽象方法
抽象父类
非抽象方法,切在具体子类的中才需要全部实现
简述
简构
抽象类中的方法必须被重写吗
问题
类、抽象类与接口
不可多继承,可单继承类或虚拟类;可以多实现类或虚拟类。
继承(extends)和实现(implements)
例子:混入类属性、方法以及静态属性和方法的使用
mixins(混入类)(with)
extension HttpManagerExtension on HttpManager {}
在Dart中,扩展(Extension)是使用静态方法扩展现有类的一种语法糖。和oc中类比一样。它允许开发者在不修改类本身的情况下为类添加新的方法和功能。通过使用扩展,我们可以为Dart内置类、自定义类甚至第三方库的类添加方法,以满足特定的需求。扩展的定义格式如下:```dartextension ExtensionName on ClassName { // 添加方法和功能}```其中,`ExtensionName`是我们自定义的扩展名称,`ClassName`是要扩展的类名。通过在扩展内部定义方法和功能,我们可以像调用类的实例方法一样使用它们。例如,假设我们有一个字符串,并希望将其转换为整数。虽然字符串类本身并没有提供这样的方法,但我们可以使用扩展为其添加一个`toInt`方法:```dartextension StringExtension on String { int toInt() { return int.parse(this); }}void main() { int number = '123'.toInt(); print(number); // 输出: 123}```在上面的例子中,我们为`String`类添加了一个`toInt`扩展方法。在`main`函数中,我们可以直接调用字符串实例的`toInt`方法,将字符串转换为整数。除了定义方法,扩展还可以定义getter、setter和operator等。虽然扩展方法中不能使用`dynamic`类型,但支持更强大的泛型扩展。这使得代码结构更为简洁,链式调用更加流畅。使用扩展的好处是它们不会修改原始类,因此不会引入额外的继承层次或破坏类的封装性。同时,扩展方法的实现非常简单,它们是通过静态方法来实现的,与调用静态函数一样快速。总的来说,Dart中的扩展是一种强大的代码复用和增强工具,允许开发者以灵活的方式为现有类添加新的功能,而无需修改这些类的源代码。
扩展是什么?如何使用
可以示例代码// 定义扩展extension MyExtension on ParentClass { void extendedMethod() { print('This is an extended method.'); } String get extendedProperty => 'This is an extended property.';}// 定义扩展extension MyParentParentExtension on ParentParentClass { void extendedMethodParentParent() { print('This is an extended method Parent Parent.'); } String get extendedPropertyParentParent => 'This is an extended property Parent Parent.';}// 父类的父类class ParentParentClass { void parentparentMethod() { print('This is a parent method.'); } void useparentparentExtension() { // 调用扩展方法 this.extendedMethodParentParent(); // 访问扩展属性 print(this.extendedPropertyParentParent); } }// 父类class ParentClass extends ParentParentClass { void parentMethod() { print('This is a parent method.'); }}// 子类class ChildClass extends ParentClass { void childMethod() { print('This is a child method.'); } void useExtension() { // 调用扩展方法 this.extendedMethod(); // 访问扩展属性 print(this.extendedProperty); } }void main() { var child = ChildClass(); // 调用子类方法 child.childMethod(); // 调用父类方法 child.parentMethod(); /// 父类的扩展属性和方法 // 调用父类的扩展方法和属性 child.useExtension(); // 间接直接调用父类的扩展方法和属性 child.extendedMethod(); /// 父类的父类的扩展属性和方法 // 间接使用父类的父类的扩展属性和扩展方法 child.useparentparentExtension(); // 直接调用父类的父类的扩展方法和属性 child.extendedMethodParentParent();}// 执行的结果// This is a child method.// This is a parent method.// This is an extended method.// This is an extended property.// This is an extended method.// This is an extended method Parent Parent.// This is an extended property Parent Parent.// This is an extended method Parent Parent.
子类是否可以方法父类的扩展,以及父类的父类的扩展呢?扩展可以继承吗?
延展
扩展(extension)
可调用的对象
继承❌:extend a 继承类,单继承
组合✅
类和抽象类都不可以多继承可以通过实现多个协议或者mixin的方式实现多继承在 Dart 中,尽管直接的多继承是不允许的,但可以通过一些其他方式来实现类似的效果,以达到多继承的目的。以下是一些常见的模式和技巧:使用 Mixin: Mixin 是 Dart 中一种特殊的类,它提供了一种在多个类之间共享功能的方式。通过 with 关键字,可以将 Mixin 类的功能混入到其他类中。mixin A { void methodA() { print(\"Method A\"); }}mixin B { void methodB() { print(\"Method B\
如何实现多继承
类
Dart语言
异步编程则是在单线程中更高效地处理并发任务的方式。使用 async 和 await 关键字,以及 Future 类,可以编写异步的代码,从而更有效地利用单线程的执行能力。
是什么:Future表示异步操作的结果,可以有两种状态:未完成或已完成。
在异步编程中随处可见,代表了事件结果
对异步编程的异常捕获
then
catchError
then或catchError任意执行后执行
whenCompelete
timeout
单Future
使用方法
示例代码:Future result = costlyQuery(url);result .then((value) => expensiveWork(value)) .then((_) => lengthyComputation()) .then((_) => print('Done!')) .catchError((exception) { /* Handle exception... */});
串联多个Future.then.then
示例代码:try { final value = await costlyQuery(url); await expensiveWork(value); await lengthyComputation(); print('Done!');} catch (e) { /* Handle exception... */}
按一定顺序分别await
串行(串联操作)
Future.wait([]) 和 await [].wait; 区别主要在异常处理上,Future.wait()只能处理最先抛出的一个异常,而Array<Future>.wait可以处理集中处理每个异常
场景举例:资源上传的,有两个步骤一个获取令牌,第二个步根据令牌信息上传文件
返回不同类型的future示例:import 'dart:async';void main() async { Future<int> delete() async { print(\"delete int\"); return 1; } Future<String> copy() async { print(\"copy string\"); return \"string from copy\"; } Future<bool> errorResult() async { print(\"errorResult bool\
可以分别处理每个Future的异常,允许多个Future抛出异常
await [].wait
只能处理最先抛出的异常
Future.wait()
不常用,仅了解即可。Future.forEach:
并发(平行操作)(parallel operations)
如果你希望多个异步操作按顺序执行,即等待一个完成后再执行下一个,使用 await。如果你希望同时开始执行多个异步操作,然后在所有操作完成后进行处理,使用 Future.wait() 或者Array<Future>.wait。通常情况下,选择取决于你的需求和性能优化。使用 await 可以更直观地表达代码的执行顺序,而 Future.wait() 可以在同时处理多个异步操作时提供更好的性能。
串行和并行的区别
多个Future
Future 四个静态方法 any、doWhile、forEach、wait 分别有什么区别,以及用法
Future Api
使用方法:https://dart.dev/tools/linter-rules/unawaited_futures
unawaited(calledMethod())
单个样例:BAD:void main() async { doSomething(); // Likely a bug.}GOOD:Future doSomething() => print(\"doSomething\");void main() async { await doSomething(); unawaited(doSomething()); // Explicitly-ignored fire-and-forget.}
await calledMethod()
await
•异步等待(Awaiting): await 关键字使异步操作的结果(Future)变为普通值(Response<T>),并暂停执行直到操作完成。•异步函数(Async Function): 使用 async 关键字声明的函数允许在内部使用 await。•隐式返回 Future: 在 async 函数中,返回的非 Future 类型的值会被自动包装成 Future 对象。•自动化操作: 这种行为是 Dart 语言设计的一部分,使异步编程更加简洁和一致。
汇总
用法
Future是什么
async声明为异步方法,返回Future
async
Future<int> fetchNumber() async { // throw Exception(\"An error occurred!\"); // 抛出异常,执行catchError,whenComplete也会执行无论是否成功完成就会执行。 await Future.delayed(Duration(seconds: 4)); print(\"fetchNumber done.\"); return 42;}void main() { fetchNumber().then((result) { print(\"Result: $result\"); }).catchError((error) { print(\"Error: $error\"); }).whenComplete(() { print(\"Operation completed.\
示例代码
示例
await等待执行结果,异步变同步(多个异步串行执行)
initstate中调用异步操作,不得已不要加await
例子
异步编程(async、Future、await和)
Stream在Dart中是一个核心概念,简称 “流”,用于处理异步事件流。简单来说,Stream可以看作是发出的一系列异步数据。与集合(Iterable或Collection)不同,集合表示一系列的对象,而Stream表示的是异步的事件流。这意味着Stream中的数据或事件不是主动拉取的,而是异步产生的并推送给接收者。Stream主要有两种类型:1. 单订阅Stream(Single-Subscription):这种Stream只包含一个事件序列,事件需要按顺序提供,不能丢失。例如,读取一个文件或接收一个网页的内容。2. 广播Stream(Broadcast):这种Stream针对单个消息的,一次处理一个消息。它可以在任何时候监听,支持添加多个监听器,并允许随时取消监听。一个常见的例子是浏览器的鼠标事件。使用Stream时,主要有两种方式接收数据:1. 使用异步for循环(async for):这是一个专门用于遍历Stream的语法结构,它会在每个异步事件到达时进行处理。2. 使用Stream的listen方法:这个方法允许你注册一个回调函数,当Stream中有新的事件产生时,这个函数会被调用。此外,Stream还常常与转换(transform)操作一起使用,以便对事件流进行各种处理,如映射、过滤等。这些转换操作可以链式调用,形成一个处理管道,从而方便地对Stream中的数据进行复杂的处理。总的来说,Stream是Dart中处理异步事件流的重要工具,它使得开发者能够以一种高效且灵活的方式处理异步数据。通过合理使用Stream及其相关操作,可以大大提高程序的性能和响应速度。
Stream是什么 ,有几种,如何使用
Stream(流) 在 Dart API 中也经常出现,表示发出的一系列的异步数据。 Stream 是一个异步数据源,它是 Dart 中处理异步事件流的统一 API。
异步事件流
StreamBuilder+StreamController
StreamController.listen
await for
监听用户输入
场景:多用于事件传递、文件读取、异步循环等场景
StreamController (.listen((entity) {}))
StreamBuilder
Stream API
listen和await for 详细的区别
dart实现监听用户输入 并展示到text widget上 需要使用await for 吗
问答
StreamBuilder、StreamController、await for 三种方式有什么区别
await for(final entity in list){}
使用Stream和await for循环来遍历数据的好处是什么
asynchronous for loop
操作订阅者:取消、异常、暂停继续
单订阅流和广播订阅流初始化有什么区别,分别是如何初始化的
广播模式:允许多个订阅者Stream有两种订阅模式:单订阅和多订阅。单订阅就是只能有一个订阅者,上面的使用我们都是单订阅模式,而广播是可以有多个订阅者。通过 Stream.asBroadcastStream() 可以将一个单订阅模式的 Stream 转换成一个多订阅模式的 Stream,isBroadcast 属性可以判断当前 Stream 所处的模式。
使用指南:https://dart.dev/guides/libraries/library-tour#stream
Stream:简单发布订阅模型
像进程一样的线程
事件驱动
微任务队列的优先级是最高的跟普通的任务并列好几个的时候,就算是微任务后提交,也会先把微任务执行完,之后再执行普通的任务!
会不会插队执行呢?会。
微任务队列
事件队列与微任务队列
是什么,如何使用
应用场景有哪些?
isolate(Dart中的异步机制)
future、stream、isolate的区别,以及各自的应用场景
总结
https://www.jianshu.com/p/d4df418244e8
阅读
异步编程
https://github.com/flutter/flutter/wiki/Flutter-build-release-channels
查看发布渠道:flutter channel
发布渠道
查看dart版本:dart --version查看flutter版本:flutter --versionpub.yaml文件environment: sdk: '>=2.18.2 <3.0.0' # dart sdk version flutter: \">=2.5.0\" # flutter sdk version
版本
dart升级
使用flutter upgrade命令可以升级到Flutter的最新版本。该命令会检查可用的Flutter SDK版本,并将您的Flutter环境升级到最新的稳定版本。请注意,升级后的版本可能会引入一些不兼容的更改,因此建议在升级之前仔细阅读Flutter的更新日志,并根据需要进行必要的调整。另外,如果您想要升级到特定的Flutter版本,可以使用flutter upgrade v<version_number>命令,将<version_number>替换为您想要升级到的特定版本号。但请注意,只能升级到已发布的版本,并且需要确保该版本与您的应用程序兼容。
官方文档:https://flutter.cn/docs/release/upgrade
flutter upgrade
查看flutter版本:flutter --version
产看版本
https://flutter.cn/docs/release/archive?tab=macos
Flutter SDK 归档列表:https://flutter.cn/docs/release/archive?tab=macos
归档列表
https://www.jianshu.com/p/4567f9509ba3
三方讲解
如何升级
flutter sdk升级
环境配置
flutter pub get
flutter pub outdated
依赖库pub
flutter build
编译打包
确保正确绑定引擎和正确的初始化应用。(确保在 Flutter 应用程序启动时,框架和引擎之间的必要绑定的建立。)
入口函数
main
`WidgetsFlutterBinding.ensureInitialized();` 是用于确保在 Flutter 应用程序启动时,框架(Flutter Framework)与引擎(Flutter Engine)之间的绑定已经被正确初始化。在 Flutter 中,有三个主要的绑定(Binding):1. **WidgetsFlutterBinding:** 负责构建和维护 Widget 树,并将它们与渲染树连接起来。`WidgetsFlutterBinding` 是框架与引擎之间的桥梁,管理整个应用程序的生命周期。2. **ServicesBinding:** 处理底层平台服务,例如输入、触摸事件、定时器等。3. **SchedulerBinding:** 负责调度和处理帧(Frame)以及处理动画等任务。`ensureInitialized` 方法是 `WidgetsFlutterBinding` 类的一个静态方法,用于确保在使用这个绑定的功能之前,绑定已经被正确地初始化。如果尚未初始化,`ensureInitialized` 方法将触发初始化过程。所以,`WidgetsFlutterBinding.ensureInitialized();` 的作用是确保在执行其他 Flutter 框架相关操作之前,`WidgetsFlutterBinding` 已经被初始化。这有助于确保应用程序能够正常运行并使用 Flutter 框架提供的功能。
是什么❓了解绑定做了什么,flutter框架
确保在应用业务初始化操作之前,框架(Flutter Framework)与引擎(Flutter Engine)之间的绑定已经被正确初始化。
作用是什么
WidgetsFlutterBinding.ensureInitialized()
绑定
初始化操作:App配置、模块初始化、用户手机权限申请配置:主要进行应用级别的配置项配置。如App配置:app版本配置、开发模式和发布模式配置。网络配置:Host配置。样式配置:如状态栏样式。第三方库配置:key配置等等模块初始化:网络,缓存,以及其他业务模块和第三方组件。手机权限申请。
例如:网络、推送、地图等模块的初始化。
业务初始化
插入根控件、开始构建UI。(将根 Widget 插入 Widget 树中,并通知框架开始构建 UI。)
runApp函数
是初始化绑定、业务初始化操作、启动页面
顺序:main -> 绑定(初始化绑定) -> 业务初始化 -> runApp(启动页面)
初始化过程
Flutter 应用启动优化是提高应用程序启动性能的一项关键任务。以下是一些可以帮助你优化 Flutter 应用启动时间的方法:1. **使用 AOT 编译:** 在生产环境中,使用 Ahead-of-Time (AOT) 编译模式,而不是 Just-in-Time (JIT) 编译模式。AOT 编译可以将 Dart 代码预先编译成本地机器码,提高应用程序启动性能。 ```bash flutter build aot ```2. **延迟加载资源:** 只在需要时加载资源,例如图片、字体等。你可以使用 `Image.network` 的 `loadingBuilder` 参数来显示占位符,然后在图片加载完成后再显示真实的图片。3. **使用 `const` 构造函数:** 在构建 Widget 树时,尽量使用 `const` 构造函数来创建静态的部分。这样可以在编译时进行常量折叠,减少运行时的工作。4. **避免不必要的重建:** 使用 `const` 构造函数创建静态的 Widget,并使用 `AutomaticKeepAliveClientMixin`、`PageStorageKey` 等保持状态的方法,避免不必要的 Widget 重建。5. **使用 `async` 和 `await`:** 在需要等待的异步操作中使用 `async` 和 `await`,以确保异步任务在启动过程中不会阻塞主线程。6. **使用 `FutureBuilder`:** 如果应用程序有需要等待的异步操作,可以使用 `FutureBuilder` 来在数据准备好后再构建 UI。7. **合理使用插件:** 谨慎选择和使用 Flutter 插件,确保插件的初始化不会对应用程序启动时间产生过大的影响。8. **减少不必要的依赖:** 在 Widget 的 `build` 方法中,只声明真正需要重建的 Widget,避免过多的不必要依赖。9. **使用 Flutter DevTools:** 使用 Flutter DevTools 中的性能分析工具来识别和解决应用程序启动时的性能瓶颈。10. **减小应用程序包大小:** 通过适当的资源压缩和移除不必要的资源,减小应用程序包的大小可以加快应用程序的下载和初始化速度。11. **优化网络请求:** 如果应用程序在启动时需要进行网络请求,确保网络请求是高效和快速的,避免阻塞主线程。12. **升级 Flutter 版本:** 定期升级 Flutter 到最新的稳定版本,以获取性能和稳定性方面的改进。这些优化策略可以根据应用程序的具体情况进行调整和组合。进行性能测试和分析是评估和改进应用程序启动性能的关键步骤。
初始化优化
初始化
如果您在使用zsh时出现 \"zsh: command not found: flutter\" 的错误,这可能是因为您的zsh shell无法找到Flutter的可执行文件。这通常是因为Flutter的可执行文件路径未添加到系统的`$PATH`环境变量中。以下是一些可能的解决方法:1. **检查Flutter安装路径:** 确保您已经正确安装了Flutter,并且知道Flutter的安装路径。默认情况下,Flutter通常安装在用户的主目录下的 `~/flutter` 目录中。如果您不确定安装路径,可以使用以下命令找到: ```bash echo $HOME/flutter ```2. **将Flutter可执行文件路径添加到$PATH:** 打开您的zsh配置文件(通常是`~/.zshrc`),并确保已经将Flutter的`bin`目录添加到您的`$PATH`环境变量中。在`~/.zshrc`中添加以下行: ```bash export PATH=\"$PATH:$HOME/flutter/bin\" ``` 保存文件并重新加载zsh配置: ```bash source ~/.zshrc ```3. **重新安装Flutter:** 如果上述步骤没有解决问题,您可以尝试重新安装Flutter。确保您按照Flutter的官方安装指南进行操作。 ```bash git clone https://github.com/flutter/flutter.git -b stable --depth 1 export PATH=\"$PATH:`pwd`/flutter/bin\" ``` 请确保在zsh配置文件中将上述 `export PATH` 行添加到永久环境变量中。4. **检查zsh配置:** 确保您的zsh配置文件没有其他导致冲突的问题。有时,其他zsh配置或插件可能会影响到`$PATH`的设置。如果您尝试了上述步骤仍然遇到问题,您可能需要仔细检查您的系统环境变量和zsh配置文件,以确保正确设置了Flutter的路径。
zsh: command not found: flutter
疑难杂症
gradle版本列表:https://services.gradle.org/distributions/
Gradlew的常用命令包括:1. `./gradlew assembleRelease`:用于快速构建Release版本的App。2. `./gradlew tasks --all`:用于查看所有任务。3. `./gradlew :app:dependencies`:查看项目的依赖,包括哪些库。4. `./gradlew -v`:查看Gradle、Groovy、Ant、JVM等的版本。5. `./gradlew clean`:和clean project类似,用于清除构建文件夹。6. `./gradlew build --info`:编译并打印日志。7. `./gradlew installDebug`:编译并安装Debug包。8. `./gradlew build --info --debug --stacktrace`:调试模式并打印堆栈信息。9. 产看依赖关系:./gradlew app:dependencies --configuration releaseRuntimeClasspath此外,还可以通过添加参数来执行特定任务,例如`./gradlew assembleDebug`用于编译并打De包。更多命令可以查阅相关文档或咨询专业人士。
常用命令
allprojects { repositories { google() mavenCentral() } configurations.all { resolutionStrategy {// force 'androidx.lifecycle:lifecycle-common:2.5.1' // failOnVersionConflict() } }}
强制依赖版本
案例
gradle
jdk版本有几个地方可以设置?这几个地方的优先级?
环境
疑问
android
gradle sync 为什么每次都执行
ct_user_mixin.dart CTUserMixin
ct_driver_addorder_mixin.dart ct_driver_addorder_mixin.dart
没有实现会报错吗
mixin只作为声明
dart
疑问❓
知识点
api文档:https://api.dart.dev/stable
语法介绍:https://dart.dev/language
json解析
...
核心库介绍:https://dart.dev/guides/libraries/library-tour
Dar语言官方教程
入门
https://wiki.ducafecat.tech/blog/translation/1-10-most-useful-flutter-widgets.html#前言
博主
学习网站:https://flutter.cn/learn
官方
字典、工具
官方web版samples
try-dart
samples
dartpad
类型安全、类型推断、空安全
This means values can’t be null unless you say they can be.
空安全
术语
https://dart.dev/language/async
整体介绍
https://dart.dev/guides/libraries/library-tour#dartasync---asynchronous-programming
使用方法介绍
Future使用指南:https://dart.dev/guides/libraries/library-tour#future
await使用指南:https://dart.dev/codelabs/async-await
Stream使用指南:https://dart.dev/guides/libraries/library-tour#stream
https://dart.dev/language/concurrency
https://dart.dev/codelabs/async-await
https://dart.dev/articles/libraries/creating-streams
异步
文章
https://gallery.flutter.cn/#/
web版本效果
https://segmentfault.com/a/1190000044000610
gallery
资源
开源项目
学习工具
https://wiki.ducafecat.tech/blog/translation/5-flutter-11-best-practices.html
https://juejin.cn/book/6844733786626719757/section/6844733786727399432
Flutter完全手册
书籍
网文
Flutter学习笔记
0 条评论
下一页