Flutter学习笔记 (一)

(一)初识Flutter

1.Flutter是什么

Flutter is Google's UI toolkit for building beautiful, natively compiled applications for mobile, web, desktop, and embedded devices from a single codebase.

官方是这么描述的,简单来说,Flutter是一个UI SDK (Software Development Kit),可以进行移动端(iOS、Android),Web端,桌面的跨平台解决方案

2.Flutter的特点

  • 美观
    使用Flutter内置的Material Design 和Cupertino widget 、丰富的motion API ,平滑自然的滑动效果和平台感知,为用户带来全新的体验

  • 快速
    Flutter引擎使用C++编写,包括高效的Skia 2D渲染引擎,Dart 运行时和文本渲染库

  • 高效
    Hot Reload

  • 开放
    开源

3.Flutter 绘制原理

image.png
  • GPU将信号同步到UI线程
  • UI线程用Dart构建图层树
  • 图层树在GPU线程进行合成
  • 合成后将视图数据提供给Skia引擎
  • Skia引擎通过OpenGL 或者 Vulkan 将内容提供给GPU

4.渲染引擎 Skia

Skia(全称Skia Graphics Library (SGL))就是Flutter向GPU提供数据的途径,是一个C++编写的开源图形库,能在低端设备如手机上呈现高质量的2D图形,最初由Skia公司开发,后被Google收购

  • 应用于Android、Google Chrome、Chrome OS等等当中
  • 目前, Skia已经是Android官方的图像渲染弓|擎了,因此Flutter Android
    SDK无需内嵌Skia弓|擎就可以获得Skia支持
  • 而对于iOS平台来说,由于Skia是跨平台的,因此它作为Flutter ioS渲染引
    擎被嵌入到Flutter的iOS SDK中,替代了iOS闭源的Core Graphics/Core
    Animation/Core Text ,这也正是Flutter iOS SDK打包的App包体积比
    Android要大一些的原因
  • 底层渲染能力统一了,上层开发接口和功能体验也就随即统一了,开发者再也不用操心平台相关的渲染特性了。也就是说, Skia保证了同一套代码调用在
    Android和iOS平台上的渲染效果是完全一致的。
image.png

(二)环境搭建

1.安装Flutter SDK (MacOS为例)

去官网下载最新的安装包 Flutter SDK releases - Flutter

1.解压到想要安装的路径

cd ~/development
unzip ~/Downloads/flutter_macos_v0.5.1-beta.zip

3.添加flutter相关工具到path中:

export PATH=`pwd`/flutter/bin:$PATH

4.运行 flutter doctor

运行以下命令查看是否需要安装其它依赖项来完成安装:

flutter doctor

5.配置环境

export PUB_HOSTED_URL=https://pub.flutter-io.cn //国内用户需要设置
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn //国内用户需要设置
export PATH=PATH_TO_FLUTTER_GIT_DIRECTORY/flutter/bin:$PATH

6.开发工具选择

官方推荐 Android Studio 或者 VSCode

(三)Flutter初体验

1.创建Flutter项目

可以通过两种方式创建,1 终端 2.编辑器 ,以终端为例

flutter create myapp
$ cd myapp

上述命令创建一个Flutte让项目,项目名为myapp,其中包含一个使用Material 组件的简单演示应用程序。

在项目目录中,您的应用程序的代码位于 lib/main.dart.

2.运行应用程序

  • 检查设备是否在运行。如果没有显示, 请参照 设置.
$ flutter devices
  • 运行 flutter run 命令来运行应用程序:
$ flutter run

3.体验热重载

Flutter 可以通过 热重载(hot reload) 实现快速的开发周期,热重载就是无需重启应用程序就能实时加载修改后的代码,并且不会丢失状态(译者语:如果是一个web开发者,那么可以认为这和webpack的热重载是一样的)。简单的对代码进行更改,然后告诉IDE或命令行工具你需要重新加载(点击reload按钮),你就会在你的设备或模拟器上看到更改。

打开文件lib/main.dart
将字符串
'You have pushed the button this many times:' 更改为
'You have clicked the button this many times:'
不要按“停止”按钮; 让您的应用继续运行.
要查看您的更改,请调用 Save (cmd-s / ctrl-s), 或者点击 热重载按钮 (带有闪电图标的按钮).

(四) 认识 Dart

1.安装Dart

为什么还需要安装Dart呢?
事实上在安装Flutter SDK的时候,它已经内置了Dart了,我们完全可以直接使用Flutter去进行Dart的编写并且运行。
但是,如果你想单独学习Dart,并且运行自己的Dart代码,最好去安装一个Dart SDK。

官方网站:https://dart.dev/get-dart,下载完成后,根据路径配置环境变量即可。
以VSCode为例,去扩展添加Dart插件

image.png

2.hello Dart

在VSCode中新建一个helloWorld.dart文件

main(List<String> args) {
  print('Hello World');
}

执行快捷键 control + option + N

3.程序分析

一、Dart语言的入口也是main函数,并且必须显示的进行定义;

二、Dart的入口函数main是没有返回值的;

三、传递给main的命令行参数,是通过List<String>完成的。

从字面值就可以理解List是Dart中的集合类型。

其中的每一个String都表示传递给main的一个参数;

四、定义字符串的时候,可以使用单引号或双引号;

五、每行语句必须使用分号结尾,很多语言并不需要分号,比如Swift、JavaScript;

(五)Dart 语法

1. 明确声明(Explicit)

明确声明变量的方式, 格式如下:

变量类型 变量名称 = 赋值;

String name = 'abc';
int age = 18;
double height = 1.88;
print('${name}, ${age}, ${height}'); // 拼接

注意事项: 定义的变量可以修改值, 但是不能赋值其他类型

2. 类型推导(Type Inference)

类型推导声明变量的方式, 格式如下:

var/dynamic/const/final 变量名称 = 赋值
2.1. var的使用

runtimeType用于获取变量当前的类型

var name = 'abc';
name = 'kobe';
print(name.runtimeType); // String

//var age = 18;
//age = 'why'; // 不可以将String赋值给一个int类型
2.2. dynamic的使用
dynamic name = 'abc';
print(name.runtimeType); // String
name = 18;
print(name.runtimeType); // int
2.3. final&const的使用

final和const都是用于定义常量的, 也就是定义之后值都不可以修改

final name = 'coderwhy';
name = 'kobe'; // 错误

const age = 18;
age = 20; // 错误

final和const有什么区别呢?

const在赋值时, 赋值的内容必须是在编译期间就确定下来的

final在赋值时, 可以动态获取, 比如赋值一个函数

String getName() {
  return 'abc';
}

main(List<String> args) {
  const name = getName(); // 错误的做法, 因为要执行函数才能获取到值
  final name = getName(); // 正确的做法
}

3.数据类型

3.1 数字类型

对于数值来说,我们也不用关心它是否有符号,以及数据的宽度和精度等问题。只要记着整数用int,浮点数用double就行了。Dart中的intdouble可表示的范围并不是固定的,它取决于运行Dart的平台。


// 1.整数类型int
int age = 18;
int hexAge = 0x12;
print(age);
print(hexAge);

// 2.浮点类型double
double height = 1.88;
print(height);

字符串和数字间转化

// 1.字符串转数字
var one = int.parse('111');
var two = double.parse('12.22');
print('${one} ${one.runtimeType}'); // 111 int
print('${two} ${two.runtimeType}'); // 12.22 double

// 2.数字转字符串
var num1 = 123;
var num2 = 123.456;
var num1Str = num1.toString();
var num2Str = num2.toString();
var num2StrD = num2.toStringAsFixed(2); // 保留两位小数
print('${num1Str} ${num1Str.runtimeType}'); // 123 String
print('${num2Str} ${num2Str.runtimeType}'); // 123.456 String
print('${num2StrD} ${num2StrD.runtimeType}'); // 123.46 String
3.2 bool类型

Dart提供了一个bool的类型, 取值为true和false

var isFlag = true;
print('$isFlag ${isFlag.runtimeType}');

Dart中不能判断非0即真, 或者非空即真
不能使用if(非booleanvalue)或assert(非booleanvalue)之类的代码。

 var message = 'Hello Dart';
  // 错误的写法
  if (message) {
    print(message)
  }
3.3 字符串类型

Dart字符串是UTF-16编码单元的序列。可以使用单引号或双引号创建一个字符串:

// 1.定义字符串的方式
var s1 = 'Hello World';
var s2 = "Hello Dart";
var s3 = 'Hello\'Fullter';
var s4 = "Hello'Fullter"

可以使用三个单引号或者双引号表示多行字符串:

// 2.表示多行字符串的方式
var message1 = '''
哈哈哈
呵呵呵
嘿嘿嘿''';

字符串和其他变量或表达式拼接: 使用${expression}, 如果表达式是一个标识符, 那么{}可以省略

// 3.拼接其他变量
var name = 'ABC';
var age = 18;
var height = 1.88;
print('my name is ${name}, age is $age, height is $height');
3.4 集合类型
3.4.1 集合类型的定义

Dart内置了最常用的三种:List / Set / Map


// List定义
// 1.使用类型推导定义
var letters = ['a', 'b', 'c', 'd'];
print('$letters ${letters.runtimeType}');

// 2.明确指定类型
List<int> numbers = [1, 2, 3, 4];
print('$numbers ${numbers.runtimeType}');


// Set的定义
// 1.使用类型推导定义
var lettersSet = {'a', 'b', 'c', 'd'};
print('$lettersSet ${lettersSet.runtimeType}');

// 2.明确指定类型
Set<int> numbersSet = {1, 2, 3, 4};
print('$numbersSet ${numbersSet.runtimeType}');

Set和List最大的两个不同就是:Set是无序的,并且元素是不重复的。

// Map的定义
// 1.使用类型推导定义
var infoMap1 = {'name': 'why', 'age': 18};
print('$infoMap1 ${infoMap1.runtimeType}');

// 2.明确指定类型
Map<String, Object> infoMap2 = {'height': 1.88, 'address': '北京市'};
print('$infoMap2 ${infoMap2.runtimeType}');
3.4.2 集合的常见操作
// 获取集合的长度
print(letters.length);
print(lettersSet.length);
print(infoMap1.length);

// 添加/删除/包含元素
numbers.add(5);
numbersSet.add(5);
print('$numbers $numbersSet');

numbers.remove(1);
numbersSet.remove(1);
print('$numbers $numbersSet');

print(numbers.contains(2));
print(numbersSet.contains(2));

// List根据index删除元素
numbers.removeAt(3);
print('$numbers');

// Map的操作
// 1.根据key获取value
print(infoMap1['name']); 

// 2.获取所有的entries
print('${infoMap1.entries} ${infoMap1.entries.runtimeType}'); // (MapEntry(name: why), MapEntry(age: 18)) MappedIterable<String, MapEntry<String, Object>>

// 3.获取所有的keys
print('${infoMap1.keys} ${infoMap1.keys.runtimeType}'); // (name, age) _CompactIterable<String>

// 4.获取所有的values
print('${infoMap1.values} ${infoMap1.values.runtimeType}'); // (why, 18) _CompactIterable<Object>

// 5.判断是否包含某个key或者value
print('${infoMap1.containsKey('age')} ${infoMap1.containsValue(18)}'); // true true

// 6.根据key删除元素
infoMap1.remove('age');
print('${infoMap1}'); // {name: why}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,340评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,762评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,329评论 0 329
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,678评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,583评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,995评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,493评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,145评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,293评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,250评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,267评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,973评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,556评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,648评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,873评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,257评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,809评论 2 339

推荐阅读更多精彩内容