471Flutter学习笔记
2021-08-01 09:36:24 3 举报
AI智能生成
Flutter学习笔记
作者其他创作
大纲/内容
Dart语言
变量
在dart语言中:<br>变量是一个引用,未初始化的变量值是null;<br>
Object、var与dynamic
Dart所有的变量皆对象
int是一个类<br>所有的基本类型都是一个class类,是与java中不同的;<br>
例如int:<br>abstract class int extends num
var 在声明的变量赋值那一刻,就决定了它是什么类型<br>
例如:<br>var j = "yulinmufeng";<br>j=100;(报错)<br><br>var l;<br>j = "yulinmufeng";<br>j=100;<br>
常量修饰符的区别:<br>dynamic与var的使用方法是相反的(动态的)。例如以下:<br>dynamic z = "yulinmufeng";<br>z= 100;<br>但在实际开发的情况下,动态的声明变量和静态的声明变量,dynamic和var变量定义的在执行效率上,不如var定义的变量;<br>dynamic一般在不确定是什么类型的时候,才会使用dynamic来声明变量;<br>dynamic一般使用频率不是很高;<br>var的缺点是,不能很好一眼就看出来是什么类型;<br>object与java中的表现是一样的;<br>
final与const的区别
final
final:<br>用法与java中是一样的;<br>
const
const:<br>在赋值之后,是不能再次进行赋值的,与final是一样的;<br>final是运行期常量;<br>const是编译期常量;<br>const比final的运行效率要高;<br>
特性:<br>final i = 1;<br>const j = 1;<br>//因为i是运行时确定,所以不能给编译时候就要确定的变量赋值<br>//const z= i;(不可以)<br><br>//可以使用另一个编译时确定的变量给它赋值<br>const z=j+1;(这样是可以的)<br>
使用场景:<br>均可以声明一个不可变量的声明<br>
内置类型<br>
数据类型:num
int
说明:<br>1、通过源码中的注释,可以看出int类型,占用的字节,要看编译运行的平台,<br>分为4字节或者8字节,但可以认为和java一样,为4个字节;<br>2、dart当中的int,在编码的时候,可以将int当成java的int long来使用,如果我们写的<br>dart代码超过了4个字节,那么dart会将其编译成类似的java当中的long否则编译成java当中的<br>short或者int;<br>3、i.bitlength=占用的字节;<br>4、在使用上和java的方式是一样的;<br>备注:原则上java和Dart语言中的int不能拿到一块进行对比,因为Dart中为class类,而java是基本<br>数据类型;<br>
double
说明:<br>1、如果要表示float类型时,只能使用double来表示;<br>2、Dart中的double和在java中的double在使用方式上市一样的;<br>
说明:<br>1、num内置数据类型只有两个int和double;<br>
字符串类型:String
说明:<br>1、在声明上与java一样;<br>String str = "走,一起去搓澡!";(dart)<br>2、方法String.format("&s%d",str,i);java中格式化一个字符串;<br>3、在Dart中更方便来格式化字符串,<br>String txt = "$str$num";(Dart语言字符串拼接)<br>String txt = "${str}s去搓澡$num";<br>4、在Dart中可以使用单引号和双引号两种声明方式,所以可以混合使用;<br>String s1 = "'test'";<br>String s2 = '"test"';<br>5、r前缀,就不进行换行------s3 = r"\n"<br>6、三引号使用"""sss"""<br>三引号在使用的时候,是可以进行内容换行的;<br>
布尔类型:bool
说明:<br>1、bool来定义布尔类型;<br>2、定义方式:<br>bool b= false;<br>
数据类型:List
说明:<br>1、List数组<br>2、Dart语言泛型<br>List<String> list = new List();<br>3、直接在声明的时候赋值<br>List<int> list = [1,2,3,4,5];<br>4、Dart语言取数据(像java数组一样通过下标取元素)<br>int item0 = list[0];<br>5、遍历数组(与java中相似)<br>for(var o in list){<br>}<br><br>for(var j= 0; j < list.length; ++j){<br>}<br>6、List对象不可变(const [1,2,3,4,5] = 意思就是可以再进行添加任何的元素)<br>List<int> list = const [1,2,3,4,5];<br>list.add(1);报错了<br>7、const修饰的是变量,也就是引用,那么变量就不能够在重新引用其他的对象了<br>const List<int> list = [1,2,3,4,5];<br>list = [3,4];报错了<br>list.add(1);报错了
映射集合:Map
说明:<br>1、声明一个映射集合如下:<br>Map<int,int> map = {1:1,2:2,3:3};<br>map[1]输出值=1,通过key来获取value;<br>2、修改一个元素的话,也是可以用个key来修改value的值<br>map[1] = 100;<br>3、用const声明map和list是一样的;<br>var map1 = const{1:1,2:2};<br>const var map1 = {1:1,2:2};<br>如果取一个不存在的数据会返回null;<br>4、迭代器遍历与java是一样的<br>
Unicode:Runes
说明:<br>1、Runes:特殊字符表示类,其实真正表示的是,Unicode32=字符编码标准,这个标准可以表示任何<br>字符,就是所有的字符;<br>2、var clapping = '\u{1f44f}';//5个16进制需要使用{},用字符串数据一个拍手的图标<br>3、代码点与代码单元(可以自己去搜索一下,这两个的区别)<br>
标识符:Symbols
说明:<br>1、(很少用到,作为了解)Symbols标识符,类似C、C++中的宏(但不完全相似)<br>2、定义一个symbols<br>var a = #asdfg;<br>a输出的时候就是为:symbols<br>使用点一般在switch中使用,其他的使用点就不多;<br>switch(a){<br> case #A:<br> break;<br> case #sadsad:<br> break;<br>}<br>
说明:<br>java中有8大基本数据类型;<br>Dart中有7大内置类型;<br>
操作符
类型判定操作符
类型转换:as<br>
说明:<br>1、Dart语言中不支持java中强制类型转换的方法<br>2、Dart例如:<br>num j = 1;<br>//类型转换,不支持java的转化:(int)强转写法<br>int i = j as int;<br>
类型判断:is、!is
说明:<br>1、dart语言中没有java中的instantof,而是需要is来实现;<br>if(index is int){<br>}<br>2、不属于int类型则命中if<br>if(index is! int){<br>}<br>
赋值操作符:??=
说明:<br>1、java保证k后续使用时一定不为null<br>String k;<br>if(null == k){<br> k = "123";<br>}<br>2、dart语言中,??= 安全赋值,如果k有值,这句话就当它不存在,如果k没有值就赋值456<br>k ??= "456";<br>
条件表达式
三目表达式:condition?expr1:expr2
说明:<br>1、跟java中的三目运算符是一样的<br>
expr1 ?? expr2<br>
说明:<br>1、如果expr1不为null,那么就返回expr1,否则就返回expr2<br>例如:<br>String k = "123";<br>var v = k ?? "789";<br>那么v= 123;<br>如果:<br>k = null;<br>var v = k ?? "789";<br>那么v = 789;<br>
级联操作符:..<br>
说明:<br>1、java中的话,就像是建造者是一样的,在每次返回的时候,都是他本身,这样的话就可以一直链式调用;<br>2、dart中级联操作符<br>new Builder()..a()..b();<br><br>class Builder {<br> void a(){<br> }<br> void b(){<br> }<br>}<br>
安全操作符:?.
说明:<br>1、在正常开发的时候,经常遇到的异常就是空指针异常;<br>但是在dart语言中,可以使用?.来解决这个功能。<br>2、grovy和kotlin语言中都有这个?.此功能。<br>
方法
可选命题参数<br>
说明:<br>1、可选命题参数又名可选命名参数,并且在使用的时候,跟可选位置参数,有点相似;如下:<br>void fun({int i,int j}){}<br>在上面方法调用的时候,传递的参数,要以键值对的形式进行传递;如下:<br>fun(j:10,i:11);//这样调用<br>2、也可以设置默认参数值的;如下:<br>void fun({int i = 2,int j}){}<br>3、应用场景,不需要再像java一样,写一大堆的重载函数,并且能够提供参数默认值;<br>
可选位置参数
说明:<br>1、java中没有;<br>2、dart语言中<br>void fun([int i, int j]){}<br>可选参数位置,只要是用[]括起来的参数,这个方法在被调用的时候,就可以传递想要传递的参数,<br>但是在参数传递的时候,也可以在参数中,直接给参数进行辅助,就是固定的参数,就设置为默认值;<br>如:void fun([int i, int j = 2]){}<br>如上如果要给j就行传值的话,就必须保证要给i传值,因为有位置要求;<br>3、应用场景,不需要再像java一样,写一大堆的重载函数,并且能够提供参数默认值;
默认参数值
一等方法对象
说明:<br>1、<br>void fun(Function f){<br>}<br><br>void main(){<br> //方法都是对象,可以赋值给Function变量<br> Function f = fun;<br> f((int i,int j,String str){<br> return "1";<br> });<br>}<br>以上代码运行报错,原因是参数对象不匹配,传的是Function,但是参数值确实多个;<br><br>//定义一个类型:F类型,这个F类型其实就是一个方法,接受两个int 参数,返回void<br>typedef void F(int i,int j);<br><br>void fun2(F f){<br> f(1);报错,此时会检测传递了几个参数;<br>}<br><br>2、在java中接口调用的方法,在dart中也是不同的;<br>java如下:<br>class OnClickListener{<br> void onClick(){}<br>}<br><br>class Button{<br> void setOnClickListener(OnClickListener listener){<br> }<br>}<br><br>dart如下:<br>typedef void onClick();<br><br>class Button{<br> void setOnClickListener(onClick listener){<br> listener();<br> }<br>}<br><br>
匿名方法
说明:<br>1、匿名方法,lambda表达式<br>
异常
说明:<br>(1)介绍catch的参数;<br>1、dart中和java中的异常抛出不一样;如下:<br>void test(){<br> throw new Exception("你好");<br>}<br><br>void main(){<br> try{<br> test();<br> }catch(e){}<br>}<br>dart中虽然不强制你去捕获异常,但是类似java中try..catch异常也是可以的;如上面的代码;<br>2、java中针对不用的异常,就捕获不同的异常;但是在dart中是不可以的;<br>3、catch(e)中不仅可以接受一个参数e,其实可以同时接受好两个参数(最多两个参数),catch(e,s)这样;<br>e:就是抛出的异常对象;<br>s:就是调用栈信息,StackTrace<br><br>(2)根据不同的异常类型,进行不同的处理;<br>语法on TYPE catch....<br>try{<br> test();<br>}on Exception catch(e,s){<br><br>}on intcatch(e){<br><br>}on Stringcatch(e){<br><br>}
类<br>
类说明:<br>1、私有的类和属性,在dart语言中,表示方式;<br>//包括类的定义 如果使用 _ 开头,意味着这个类就是private<br>class Point{<br> int _x;//使用_开始命名的变量,就是java的private,在外面不可以调用<br> int y;<br>}<br>
构造函数
构造函数语法糖Point(this._x,this.y)
说明:<br>class Point{<br> int _x;<br> int y;<br> Point(this._x,this.y);//构造函数<br>}<br>Point(this._x,this.y);<br>此构造方法相对于java中来说,比之前要简单的多;<br><font color="#D32F2F"><b>dart语言中是不能进行方法重载的,但是我们是有定义多个方法的需求;</b></font><br>
命名构造函数
说明:<br>1、dart语言中是不能进行方法重载的,但是我们是有定义多个方法的需求;<br>命名构造方法(可以根据名字就可以直接看出来这个构造方法是干嘛用的,这也是为什么有了命名构造方法,<br>还可以有可选参数构造方法的原因):<br>Point.Y(this.y);<br>Point._X(this._X);<br>调用方式:var point = new Ponit.X(1);<br><br>2、构造方法的可选参数<br>Point(int x,int y){}//不用加this了<br>
参数初始化列表
说明:<br>参数初始化列表(初始化类中的属性,可以不写方法体):<br>Point.XY():_x=1,y=2;<br>Point.fromMap(Map map):_x = map['x'],y=map['y'];<br>
重定向构造函数
说明:<br>重定向构造函数<br>class View{<br> View(int content,int attr);<br> //重定向构造函数<br> View.a(int context):this(context,0);<br>}<br>
常量构造函数
说明:<br>class ImmutabelPoint{<br> final int x;<br> final int y;<br> //常量构造方法<br> const ImmutabelPoint(this.x,this.y);<br>}<br>使用new来创建常量构造方法的对象,就和普通的对象没有区别;<br>但是使用const来创建多个对象,传递的参数一样,表示这几个对象是同一个编译器常量对象(必须定义常量构造函数)<br>void main(){<br> var p1 = const ImmutabelPoint(1,1);<br> var p1 = const ImmutabelPoint(1,1);<br> print(p1.hashCode == p2.hashCode);//true<br> print(p1 == p2);//true<br>}<br>
工厂构造函数
说明:<br>在命名构造函数前面其实加一个factory就是工厂构造函数;<br>在工厂的构造方法中,不可以使用this<br>
Getter与Setter
说明:<br>每一个实例属性,变量都会有一个隐式的get,非final 还有set方法;<br><br>
操作符重载
说明:<br>操作符重载:把已经定义的、有一定功能的操作符进行重新定义;<br>例如:<br><、+、|、[]、>、/、^、[]=、<=、~/、&、~、>=、*、<<、==、-、%、>><br>
抽象类与接口
说明:<br>1、abstract<br>使用abstract修饰符定义一个抽象类,抽象类中允许出现无方法的方法与java没有什么区别,不可以多继承;<br>abstract class Parent{<br> String name;<br> void printName();//抽象方法,不需要在方法前声明abstract<br>}<br><br>2、接口<br>与java不同,Dart中没有interface关键字,Dart中每个类都隐式的定义了一个包含所有势力成员的接口,<br>并且这个类实现了这个接口。如果你想创建类M来支持类N的方法,而不想继承N的实现,则类M应该实现N的接口;<br>每一类都可以看作为一个接口,Dart语言中没有分的太清楚。<br><br>
混合mixins
说明:<br>Mixins是一种在多类继承中重用一个类代码的方法;而且被Mixins侵入的类<br>不能有构造函数。<br>此功能就是相对于弥补java不能多继承的问题;<br>class A{<br> void a(){}<br>}<br>class B{<br> void b(){}<br>}<br>class C with A,B{<br> void c(){}<br>}<br>还有一种写法:<br>class C = Object with A,B;//C类就是AB的混合类;<br>可以在C类中调用AB类中的方法,满足了我们的多继承的需求,但是不能重写;<br><br>使用混入的话可以弥补我们没有多线程的缺陷;<br>
可调用的类
说明:<br>class Test{<br> void call()}{}<br>}<br>调用(只有call方法的时候才能这样调用)<br>test();就相当于调用了call()方法;<br>也可以直接调用<br>test.call();<br>
环境搭建
Flutter配置开发环境<br>
(0)网址:https://flutterchina.club/setup-windows/
(1)使用镜像配置环境变量
同时可以在用户中心和系统中心进行配置环境变量<br>
mac
说明:以下是mac本配置的方式:(与window方式不一样,但是Flutter中文网上给的镜像的方式是错误的,给的mac上配置的方式,特此说明)<br>export PUB_HOSTED_URL=https://pub.flutter-io.cn<br>export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
window
说明:window配置镜像的方式如下。<br>PUB_HOSTED_URL=https://pub.flutter-io.cn<br>FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
(2)下载Flutter的SDK
网址:https://flutter.dev/docs/development/tools/sdk/releases#windows
下载完成之后,进行解压,然后在进行环境变量的配置<br>配置到path路径下。<br>
环境变量配置:<br>D:\install_files\flutter\flutter_sdk\flutter\bin<br>配置完成之后,<br>现在就可以使用flutter命令了<br>
命令测试
打开cmd命令,执行以下命令:<br>flutter doctor<br>执行结果可以查看,flutter需要的条件有哪些,哪些还没有安装,都会给你列出来。<br>(如上图)<br>
(3)安装插件
以上所有工作已经完成后<br>打开android studio进行安装Flutter插件,安装成功后,对android studio进行重启<br>然后在创建新项目的时候,就可以创建flutter项目了<br>
(4)所有的准备工作已经完成
(5)遇到的第一个问题
错误日志如下:<br>Could not determine the dependencies of task ‘:app:compileDebugJavaWithJavac‘.
解决方法:<br>1、修改android目录下的build.gradle文件中的所有的google()和jcenter()换成阿里云的镜像<br>
buildscript {<br> ext.kotlin_version = '1.3.50'<br> repositories {<br>// google()<br>// jcenter()<br> maven { url 'https://maven.aliyun.com/repository/google' }<br> maven { url 'https://maven.aliyun.com/repository/jcenter' }<br> maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }<br> maven { url 'http://download.flutter.io'}<br> }<br><br> dependencies {<br> classpath 'com.android.tools.build:gradle:4.1.0'<br> classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"<br> }<br>}<br><br>allprojects {<br> repositories {<br>// google()<br>// jcenter()<br> maven { url 'https://maven.aliyun.com/repository/google' }<br> maven { url 'https://maven.aliyun.com/repository/jcenter' }<br> maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }<br> maven { url 'http://download.flutter.io'}<br> }<br>}<br><br>rootProject.buildDir = '../build'<br>subprojects {<br> project.buildDir = "${rootProject.buildDir}/${project.name}"<br> project.evaluationDependsOn(':app')<br>}<br><br>task clean(type: Delete) {<br> delete rootProject.buildDir<br>}<br>
解决方法:<br>2、修改flutter sdk下的flutter.gradle文件,具体目录是flutter\packages\flutter_tools\gradle
buildscript {<br> repositories {<br> maven { url 'https://maven.aliyun.com/repository/google' }<br> maven { url 'https://maven.aliyun.com/repository/jcenter' }<br> maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }<br> }<br> dependencies {<br> classpath 'com.android.tools.build:gradle:3.5.0'<br> }<br>}<br>
异步编程
isolate(Dart中的异步机制)
像进程一样的线程<br>
事件驱动
事件队列与微任务队列
微任务队列的优先级是最高的<br>跟普通的任务并列好几个的时候,就算是微任务后提交,也会先把微任务执行完,之后再执行普通的任务!<br>
微任务队列
会不会插队执行呢?
Futura
在异步编程中随处可见,代表了事件结果<br>
对异步编程的异常捕获
等待多个异步结果进行后续操作:wait方法<br>
Stream
异步事件流
Stream(流) 在 Dart API 中也经常出现,表示发出的一系列的异步数据。 Stream 是一个异步数据源,它是 Dart 中处理异步事件流的统一 API。
操作订阅者:取消、异常、暂停继续
广播模式:允许多个订阅者<br>Stream有两种订阅模式:单订阅和多订阅。单订阅就是只能有一个订阅者,上面的使用我们都是单订阅模式,而广播是可以有多个订阅者。通过 Stream.asBroadcastStream() 可以将一个单订阅模式的 Stream 转换成一个多订阅模式的 Stream,isBroadcast 属性可以判断当前 Stream 所处的模式。
async/await
async声明为异步方法,返回Future
await等待执行结果,异步变同步(多个异步串行执行)
使用`async`和`await`的代码是异步的,但是看起来很像同步代码。当我们需要获得A的结果,再执行B,时,你需要`then()->then()`,但是利用`async`与`await`能够非常好的解决回调地狱的问题
示例<br>
//async 表示这是一个异步方法,await必须再async方法中使用<br>//异步方法只能返回 void和Future<br>Future<String> readFile() async {<br> //await 等待future执行完成再执行后续代码<br> String content = await new File("/Users/xiang/enjoy/a.txt").readAsString();<br> String content2 = await new File("/Users/xiang/enjoy/a.txt").readAsString();<br> //自动转换为 future<br> return content;<br>}
0 条评论
下一页