目录导航
新建Flutter项目
File→New→New Flutter Project,
四种创建方式的区别:
- Flutter Application
创建一个Flutter 应用程序,这也是我们创建一个全新的Flutter项目的常用方式。 - Flutter Package
创建一个代码库,dart把代码库统称为“package”,类似于android项目中的library,可发布至Pub site供他人依赖使用。 - Flutter Plugin
创建一个插件库,插件库是特殊的Flutter Package,用于开发针对特定平台(android/ios)API的代码库,并通过平台通道(platform-channel)转换为不同平台的原生代码。
例如,android开发时,通过SharedPreferences存储简单数据,Ios则通过NSUserDefaults。对于android开发人员来说,当然希望通过熟悉的SharedPreferences API来开发,然后通过平台通道自动转化为SharedPreferences(for android)和NSUserDefaults(for ios)相关的原生代码。shared_preferences便是这样一个插件库。 - Flutter Module
用于现有的Android/Ios项目集成Flutter代码。创建一个Flutter Module进行Flutter开发,然后将该Module分别集成进Android和Ios项目。
项目结构
新建一个flutter application,注意项目名必须全部为小写字母和数字的组合,用下划线分隔单词,且首字符只能为小写字母,如flutter_app。
- lib目录:存放跨平台的dart代码。
- android目录:存放android原生代码,整个目录结构与android项目完全相同。
- ios目录:存放ios原生代码。
- pubspec.yaml文件:dart配置依赖和资源的文件,类似于android项目中的build.gradle。
资源存放与引用
在android中,资源可存放于res或assets的预定义目录下,res下的每种资源还必须置于预定义的子目录中,如字符串位于values下,图片位于drawable下。flutter只有assets,但没有预定义该文件夹,你可以任意创建文件夹存放资源,这些文件夹可以是平行关系,不必位于同一目录下,名字也不必为“assets”。最后,还需要在pubspec.yaml文件里声明这些资源。注意,不要将资源文件夹放在android或ios这两个存放原生代码的目录下,dart代码访问不到。
例如,项目根目录下创建json文件夹存放json文本文件。
json文本文件的内容。
声明该资源,注意以短横线打头,短横线与资源路径之间用空格隔开。路径可以是单个文件,也可以是文件夹。当为文件夹时,等价于声明该文件夹下的所有文件,注意不包括该文件夹的子文件夹下的文件。
资源声明后,就可以通过AssetBundle访问了:
- 读取资源,解析为字节数据
DefaultAssetBundle.of(context).load("json/data.json");
- 解析为字符串
DefaultAssetBundle.of(context).loadString("json/data.json");
- 先解析为字符串,然后根据传入的函数解析为特定类型的数据,类型由传入的泛型参数决定
//解析为Person
DefaultAssetBundle.of(context).loadStructuredData<Person>(
"json/data.json",
(strValue){
//...
}
);
图片资源
项目根目录下创建一个文件夹存放图片资源,如images
声明图片资源。
android中dp意为设备无关像素,不同分辨率的图片置于不同drawable后缀的文件夹下,如drawable-hdpi。
flutter中没有dp的概念,但有与之类似的逻辑像素,如1x,2x,3x等。x前面的数字称为设备像素比率,可为任意数字。设备像素比率与andorid中dp修饰符的对照关系如下:
不同设备像素比率的图片置于不同比率名的文件夹下,不指定设备比率等价于1.0x。
images/my_icon.png // Base: 1.0x image
images/2.0x/my_icon.png // 2.0x image
images/3.0x/my_icon.png // 3.0x image
除了通用的AssetBundle可访问图片资源外,还可通过AssetImage直接显示图片。
AssetImage("images/sample.jpeg");
或
Image.asset("images/sample.jpeg");
字符串资源
android中字符串可以配置在res→values目录下的xml文件中,然后通过R.string访问。flutter没有类似的机制,官网推荐的做法——也是java中常见的方法,把常量定义为一个类的静态字段,通过该类引用它。
class Strings {
static const String introduction = "hello!我是朱志强!";
}
用Text控件显示它,
Text(Strings.introduction);
添加依赖
flutter/dart代码库发布平台Pub site
开发android项目时,可以将代码库发布至jcenter、MavenCentral等平台供他人依赖使用。flutter/dart代码库的发布平台是Pub site。你可以在这里搜索他人发布的代码库。
Pub site平台的代码库的版本号由三个被点号分隔的数字组成,如:1.0.0,还有一个可选的后缀,如:1.0.0+1,表示1.0.0 版的一个修补版本。
如果你在1.0.0版做了一个极小的修复,并没有什么大的改动,你可以将版本号改为1.0.0+1。
pubspec.yaml文件用于配置项目所依赖的代码库,类似android项目的build.gradle文件。在dart中,代码库称为“package”。
依赖配置在dependencies节点下,格式为package_name: x.y.z(+a),(+a)是可选的,package_name为代码库的名字。
版本约束
上面的依赖方式,明确指定了版本号,还可以指定版本号范围,称之为“版本约束”。版本约束有:
-
any
任意版本,例如http: any,表示可使用http库的任意版本。不指定任何约束http: 与http: any等价。 -
>,>=,<,<=
例如,http: >1.0.0,表示大于1.0.0的版本;http: <=2.5.0,小于等于2.5.0的版本;http: >1.5.0 <=2.0.0,大于1.5.0且小于等于2.0.0的版本。 -
^x.y.z
尖号语法(caret syntax),即用“^”修饰版本号。^x.y.z表示的版本号范围,
下限为:x.y.z,即>=x.y.z。
上限为:-
if x!=0,则上限为<(x+1).y.z
-
if x==0 && y!=0,则上限为<0.(y+1).z
-
if x==0 && y==0,则上限为<0.0.(z+1)
-
例如,
http: ^1.5.0,等价于http: >=1.50 <2.0.0;
http: ^0.12.0,等价于http: >=0.12.0 <0.13.0;
http: ^0.0.3,等价于http: >=0.0.3 <0.0.4,如0.0.3+2满足约束。
-
-
x.y.z
这种就是我们常见的指定一个具体的版本号。
版本约束的好处之一,就是解决潜在的版本冲突。
比如,我们的项目显示依赖库A和B,而A和B在内部都依赖C,但依赖版本不一致,A依赖C: 1.5.0,B依赖C: 2.0.0。而且A依赖的C的一个Api在C: 2.0.0版本后删除,B依赖的一个Api在C:1.7.0版本后才有,如果按照传统的冲突解决方式直接取用高版本C: 2.0.0,将会出现错误。
如果采用版本约束,A依赖C: >=1.5.0 <2.0.0,B依赖C:>=1.7.0,那么pubspec.yaml在解析依赖C时,会选取>=1.7.0且<2.0.0范围内的最新版本。
Packages get
pubspec.yaml文件内配置依赖后,可点击上方的Packages get同步一下。点击Package get会执行命令:
$ flutter pub get
它会首先解析各个依赖库的版本约束,选取符合约束的最新版本,写入pubspec.lock文件锁住。
那么,在下次点击Packages get时,会直接采用pubspec.lock中的版本,不会尝试获取符合约束的更高的版本,除非pubspec.lock中锁住的版本已不符合约束。
这么做目的何在?以上面的http库为例,我们的版本约束是http: ^0.12.0,即http: >=0.12.0 <0.13.0,目前满足版本约束的最新版本号是0.12.0+2。假设过了半年,http的最新版本为0.12.5,并且剔除了一个我们依赖的Api,如果不锁住版本,0.12.5版本依然满足版本约束,那么依赖0.12.5版本将导致代码出错。
假设我们打算重构代码,不再依赖http中废弃的Api,我们可以修改版本约束为http: ^0.12.5,那么pubspec.lock锁住的版本已不符合版本约束,再次点击Packages get时,pub会重新解析版本约束,获取满足版本约束的最新版本,并写入pubspec.lock。
Packages upgrade
在不修改版本约束的情况下,如何升级版本?就要用到下面的命令:
$ flutter pub upgrade
点击Packages get右侧的Packages upgrade执行该命令。Packages upgrade会忽略pubspec.lock文件中锁定的版本,重新解析版本约束,然后获取符合版本约束的最新版本,并更新pubspec.lock文件。
除了Packages get,Packages upgrade外,pubspec.yaml编辑器工具栏还有我们熟悉的flutter doctor命令,用于检测flutter环境及其工具的配置情况。flutter upgrade是用来升级flutter框架的命令。
依赖未发布至Pub site的代码库
依赖本地代码库
dependencies:
[package_name]:
path: [local_path]
path可以为绝对路径,也可以是相对路径。例如,依赖与本项目同级目录下的一个库one_lib,
dependencies:
one_lib:
path: ../one_lib
依赖发布至git仓库的代码库
dependencies:
[package_name]:
git:
url: [git_url]
例如,
dependencies:
one_lib:
git:
url: git@github.com:the-pig-of-jungle/one_lib.git
如果你的dart项目的根目录与git根目录不一致,你需要指定path:
dependencies:
one_lib:
git:
url: git@github.com:the-pig-of-jungle/my_packages.git
path:my_packages/one_lib