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 args) {
  print('Hello World');
}

执行快捷键 control + option + N

3.程序分析

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

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

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

从字面值就可以理解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 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 numbers = [1, 2, 3, 4];
print('$numbers ${numbers.runtimeType}');


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

// 2.明确指定类型
Set 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 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>

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

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

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

// 6.根据key删除元素
infoMap1.remove('age');
print('${infoMap1}'); // {name: why}






你可能感兴趣的:(Flutter学习笔记 (一))