移动端开发新趋势Flutter
Flutter是Google开发的新一代跨平台方案,Flutter可以实现写一份代码同时运行在iOS和Android设备上,并且提供很好的性能体验。Flutter使用Dart作为开发语言,这是一门简洁、强类型的编程语言。Flutter对于iOS和Android设备,提供了两套视觉库,可以针对不同的平台有不同的展示效果。
在Google刚推出Flutter时,其发展很缓慢,终于在18年发布第一个Bate版之后迎来了爆发性增长,发布第一个Release版时增长速度更快。可以从Github上Star数据看出来这个增长的过程。在19年最新的Flutter 1.2版本中,已经开放Web支持的Beta版。
目前运用flutter的大型项目:
- 阿里咸鱼
- 头条的抖音
- 腾讯的NOW直播
整体框架
Flutter可以理解为开发SDK或者工具包,其通过Dart作为开发语言,并且提供Material和Cupertino两套视觉控件,视图或其他和视图相关的类,都以Widget的形式表现。Flutter有自己的渲染引擎,并不依赖原生平台的渲染。Flutter还包含一个用C++实现的Engine,渲染也是包含在其中的。
hot Reload
Flutter支持亚秒级热重载,Android Studio和VSCode都支持Hot Reload的特性。但需要区分的是,热重载和热更新是不同的两个概念,热重载是在运行调试状态下,将新代码直接更新到执行中的二进制。而热更新是在上线后,通过Runtime或其他方式,改变现有执行逻辑。
类型 | React Native | flutter |
---|---|---|
语言 | JavaScript(动态语言) | dart(伪动态语言的强类型语言) |
环境 | JSCore | Flutter Engine |
发布时间 | 2015 | 2017 |
star | 78k+ | 67k+ |
对比版本 | 0.59.9 | 1.6.3 |
空项目打包大小 | Android 20M(可调整至 7.3M) / IOS 1.6M | Android 5.2M / IOS 10.1M |
代码产物 | JS Bundle 文件 | 二进制文件 |
维护者 | ||
风格 | 响应式,Learn once, write anywhere | 响应式,一次编写多平台运行 |
支持 | Android、IOS、(PC) | Android、IOS、(Web/PC) |
使用代表 | 京东、携程、腾讯课堂 | 闲鱼、美团B端 |
插件安装 | npm插件 | pub插件 |
缺点:
在跨平台开发中,就不得不说到接入原有平台的支持
,比如 在 Android 平台上接入 x5 浏览器 、接入视频播放框架、接入 Lottie 动画框架等等。
这一需求 React Native 先天就支持
,甚至在社区就已经提供了类似 lottie-react-native 的项目。 因为 React Native 整个渲染过程都在原生层中完成,所以接入原有平台控件并不会是难事 ,同时因为发展多年,虽然各类第三方库质量参差不齐,但是数量上的优势
还是很明显的。目前为止, Flutter 原生控件的接入上是仍不如
React Native 稳定
。
flutter在window环境下安装安装
-
获取最新的flutter安装包
-
更新环境变量
在“用户变量”下检查是否有名为“Path”的条目:
如果该条目存在, 追加 flutter\bin的全路径,使用 ; 作为分隔符.
如果条目不存在, 创建一个新用户变量 Path ,然后将 flutter\bin的全路径作为它的值. -
运行flutter doctor检查一下flutter基本环境,是否还需要安装什么依赖,缺什么根据提示安装什么
-
编辑器的一些配置(我自己用的Idea, 直接file->setting->plugin->安装flutter)
如何快速和运行一个flutter项目
-
可视化的方式
新建:
file -> new -> flutter启动:
点击绿色三角形启动flutter项目 -
命令行的方式:
flutter create flutter_app
运行flutter run
如何调试和使用开发工具
dart基础
参考资料:
dart常用语法
在Dart中,一切都是对象,一切对象都是class的实例,哪怕是数字类型、方法甚至null都是对象,所有的对象都是继承自Object
- 注释:
//
/*
*
*/
///
-
控制台输出: print
-
字符串使用单引号或双引号均可,如’hello’, “hello”
字符串插入可以使用类似$name
或${name}
的语法 -
Dart中变量可以以字母或下划线开头,后面跟着任意组合的字符或数字
-
数据类型:
Dart有如下几种内建的数据类型:
numbers// int double
strings
booleans
lists(或者是arrays)//List List<String>
maps// Map
runes(UTF-32字符集的字符)
symbols
Function
- 如何定义变量
你可以明确指定某个变量的类型,如int bool String,也可以用var或 dynamic来声明一个变量,Dart会自动推断其数据类型。
var a = 1;
int b = 10;
String s = "hello";
dynamic c = 0.5;
注意:没有赋初始值的变量都会有默认值null
- final和const
如果你绝不想改变一个变量,使用final或const,不要使用var或其他类型,一个被final修饰的变量只能被赋值一次,一个被const修饰的变量是一个编译时常量(const常量毫无疑问也是final常量)。可以这么理解:final修饰的变量是不可改变的,而const修饰的表示一个常量。
注意:实例变量可以是final的但不能是const的
final String name = 'zhangsan';
name = 'lisi'; // 编译不通过,被final修饰的是常量,不可重新赋值
const a = 0;
a = 1; // 错误
final和const的区别:
区别一:final 要求变量只能初始化一次,并不要求赋的值一定是编译时常量,可以是常量也可以不是。而 const 要求在声明时初始化,并且赋值必需为编译时常量。
区别二:final 是惰性初始化,即在运行时第一次使用前才初始化。而 const 是在编译时就确定值了。
- 函数
- Dart是一个面向对象的编程语言,所以即使是函数也是一个对象,也有一种类型
Function
,这就意味着函数可以赋值给某个变量或者作为参数传给另外的函数。虽然Dart推荐你给函数加上返回值,但是不加返回值的函数同样可以正常工作,另外你还可以用=>
代替return
语句, - 使用花括号将函数的参数括起来就是定义了
命名参数
,定义命名参数时,你可以以{type paramName}
或者{paramName: type}
两种方式声明参数,而调用命名参数时,需要以funcName(paramName: paramValue)的形式调用。 命名参数
的参数并不是必须
的,如果要表示一个参数是必须的,@required
注解来标识一个命名参数,这代表该参数是必须的,你不传则会报错- 使用中括号[]括起来的参数是函数的
位置参数
,代表该参数可传可不传,位置参数只能放在函数的参数列表的最后面。 - 你可以为命名参数或者位置参数设置默认值
- ***不论在Dart还是Flutter中,必须都需要一个顶层的
main()
函数,它是整个应用的入口函数
,main()函数的返回值是void - 所有的函数
都有返回值
,如果没有指定return语句,那么该函数的返回值为null
// 声明返回值
int add(int a, int b) {
return a + b;
}
// =>是return语句的简写
add3(a, b) => a + b;
sayHello({String name}) {
print("hello, my name is $name");
}
sayHello2({name: String}) {
print("hello, my name is $name");
}
const Scrollbar({Key key, @required Widget child})//child是必须的
sayHello(String name, int age, [String hobby]) { // 位置参数可以有多个,比如[String a, int b]
StringBuffer sb = new StringBuffer();
sb.write("hello, this is $name and I am $age years old");
if (hobby != null) {
sb.write(", my hobby is $hobby");
}
print(sb.toString());
}
// 命名参数的默认值
int add({int a, int b = 3}) { // 不能写成:int add({a: int, b: int = 3})
return a + b;
}
// 位置参数的默认值
int sum(int a, int b, [int c = 3]) {
return a + b + c;
}
- 运算符
Dart中的运算符与Java中的类似,比如++a a == b b ? a : b,但是也有一些与Java不太一样的运算符
main() {
// 与Java相同的运算符操作
int a = 1;
++a;
a++;
var b = 1;
print(a == b); // false
print(a * b); // 3
bool real = false;
real ? print('real') : print('not real'); // not real
print(real && a == b); // false
print(real || a == 3); // true
print(a != 2); // true
print(a <= b); // false
var c = 9;
c += 10;
print("c = $c"); // c = 19
print(1<<2); // 4
// 与Java不太一样的运算符操作
// is运算符用于判断一个变量是不是某个类型的数据
// is!则是判断变量不是某个类型的数据
var s = "hello";
print(s is String); // true
var num = 6;
print(num is! String); // true
// ~/才是取整运算符,如果使用/则是除法运算,不取整
int k = 1;
int j = 2;
print(k / j); // 0.5
print(k ~/ j); // 0
// as运算符类似于Java中的cast操作,将一个对象强制类型转换
(emp as Person).teach();
// ??=运算符 如果 ??= 运算符前面的变量为null,则赋值,否则不赋值
var param1 = "hello", param2 = null;
param1 ??= "world";
param2 ??= "world";
print("param1 = $param1"); // param1 = hello
print("param2 = $param2"); // param2 = world
// ?.运算符
var