电商类的淘宝 京东 闲鱼 使用了Flutter
今日头条 链家也使用了Flutter
Boss 喜马拉雅 上海移动(没截图了) 小红书 没有使用Flutter
1、Flutter优点
A、混合开发中,最接近原生开发的框架;
B、性能强大,流畅;
C、优秀的路由设计;
D、优秀的动画设计;
E、简单易学,Dart语言更具优势;
F、跨多种平台,减少开发成本;支持插件,可以访问原生系统的调用。
2、Flutter缺点
A、脱离不开原生,开发人员需要具备原生(Android、iOS)基础开发能力;
B、适配问题,开发工具版本升级后,修改量大;
C、原生集成第三方SDK后,兼容性适配是个令人头痛的问题;
D、代码可读性较差,对代码质量和管理要求较高;
E、Widget的类型难以选择,糟糕的UI控件API;
F、Flutter packages和Dart packages上第三方sdk繁杂,适配性差,不可乱用;
G、目前几乎没有第三方开发者平台开发Flutter能力的SDK,需要原生去集成;
H、打包后,apk/ipa要大很多。
潮流逼着你前进.
一.基本语法
'
1. dart 变量
var :变量(任何类型)
const : 常量
final : 变量(只能赋值一次)
2. 内置 类型
Number:数值型
String:字符串
Boolean:布尔型
List:列表
Map:键值对
另外还有 Runes 和Symbols 类型
举个例子
void main(){
var name = 'dex';
const age = 22;
final addr = "china";
num a = 10;
a = 12.5;
int b = 20;
double c = 10.5;
print(c);
}
注意:每一行都要以 ; 结尾
3. 数值型操作
1) 运算符 : + 、- 、* 、/ 、~/ 、%
其他都不用说和java 或者js都是相同的运用,唯有 ~/ : 是标识取余
2)常量属性:isNaN (是否非数字)、isEven(是否偶数)、isOdd(是否奇数)
3)常用方法:abs() (取绝对值)、round() (四舍五入)、floor() (向下取整【不大于基数】) 、ceil()(向上取整【不小于基数】)、toInt()、toDouble()
void main(){
int age = 40;
double score = 80.9;
int grade = -5;
print(score / age); // 2.0225
print(score % age); // 0.9000000000000057
print(score ~/ age); // 2
print(score.floor()); // 80
print(score.ceil()); // 81
print(score.round()); // 81
print(grade.abs()); // 5
print(age.isEven); // true
print(age.isOdd); // false
print(age.isNaN); // false
}
4.1 字符串(String)
定义String 使用单引号、双引号、三个引号来定义字符串和 r 来创建原始的raw字符串
void main(){
String article = ''' Hello welcome to
dart develope ceter''';
print(article); // Hello welcome to
// dart develope ceter
// use ¥ operator
String caption = r" Hello \n Lilei !";
print(caption); // Hello \n Lilei !
}
4.2 字符串操作符 : + (字符拼接) 、* (字符按参数累加)、 == (字符比对)、 [](按下标获取数据)
void main(){
String str = "This is my first proj";
print(str * 5); // This is my first projThis is my first projThis is my first projThis is my first projThis is my first proj
print(str[5]); // I
}
4.3插值表达式 ${expression}
void main(){
String name = 'jack';
int age = 20;
String addr = '四川成都';
String information = '$name今年$age岁 来自${addr}' ;
print(information); // jack今年20岁 来自四川成都
}
常用属性: length 、isEmpty 、isNotEmpty
常用方法:contains() 、subString() 、startsWith()、 endsWith() 、indexOf() 、lastIndexOf() 、toLowerCase() 、toUpperCase() 、trim() 、trimLeft() 、trimRight()、 split()、 replaceAll()、replaceFirst()
5.布尔型 bool
void main(){
bool isNice = true;
print(isNice); // true
}
6. List 列表/ 数组 (list 元素可以任意类型)
var list = [1,2,3,4,5,6]; // 普通list 创建
var list = const[1,2,3,4,5,6]; // 创建一个不可变list
var list = new List(); // 使用构造创建
void main(){
var studentList = [1,2,3 ,"hello dart",true];
print(studentList); // [1, 2, 3, hello dart, true]
print(studentList[2]); // 3
studentList[1] = 'Lilei';
print(studentList); // [1, Lilei, 3, hello dart, true]
var teacherList = new List();
teacherList[0] = 'Macke'; // Unhandled exception: RangeError (index): Invalid value: Valid value range is empty: 0 (因为这个teacherList对象只有创建了,但还未开辟内存空间)
teacherList.add( 'Macke');
print(teacherList); // [Macke]
}
常用方法:[] 、length、 add()、 insert() 、remove() 、clear() 、indexOf()、 lastIndexOf() 、sort() 、sublist() 、shuffle()、 asMap() forEach() …
void main(){
var hobbies = ["jog","swim","red"];
hobbies.insert(1,"tourism");
print(hobbies); // [jog, tourism, swim, red]
print(hobbies.indexOf("tourism")); // 1
hobbies.sort();
print(hobbies); // [jog, red, swim, tourism]
print(hobbies.sublist(1)); // [red, swim, tourism]
hobbies.shuffle(); // 打乱元素
print(hobbies); // [jog, tourism, red, swim]
hobbies.forEach(print);// jog
// tourism
// red
// swim
}
7. Map (key-val可以任何类型)
var studyPlan = {'first':'Dart','second':'Flutter'}; // 创建普通map
var studyPlan = const{'first':'Dart','second':'Flutter'}; // 创建一个不可变map
var studyPlan = new Map(); // 使用构造函数创建
void main(){
var studyPlan = {'first':'Dart','second':'Flutter','isHappy':true,true:'ok'};
print(studyPlan); // {first: Dart, second: Flutter, isHappy: true, true: ok}
print(studyPlan['first']); // Dart
print(studyPlan[true]);// ok
studyPlan[2] = false;
print(studyPlan); // {first: Dart, second: Flutter, isHappy: true, true: ok, 2: false}
}
常用方法: []、 length、 isEmpty()、 isNotEmpty() 、Keys、 values containsKey()、 containsValue() 、remove()、 forEach()…
void main(){
var studyPlan = {'first':'Dart','second':'Flutter','isHappy':true,true:'ok'};
print(studyPlan.keys); // (first, second, isHappy, true)
print(studyPlan.values); // (Dart, Flutter, true, ok)
print(studyPlan.containsKey('first')); // true
print(studyPlan.containsValue('Dart')); // true
studyPlan.remove('isHappy');
print(studyPlan); // {first: Dart, second: Flutter, true: ok}
// 调用自定义proxyPrint方法进行map
studyPlan.forEach(proxyPrint);// key=first,value = Dart
// key=second,value = Flutter
// key=true,value = ok
var list = ['lili','lulu','xinxin'];
// asMap() 将使用下标作为key ,元素作为val然后将其转换为map对象
print(list.asMap()); // {0: lili, 1: lulu, 2: xinxin}
}
void proxyPrint(key,value){
print("key=$key,value = $value");
}
8. dynamic (动态类型【根据值自动更改变量类型】)
void main(){
dynamic nickname = '小鱼儿';
print(nickname); // 小鱼儿
nickname = '雷震子';
print(nickname); // 雷震子
// 定义类型为泛型的list
var generic = new List<dynamic>();
generic.add(6);
generic.add(8.8);
generic.add('hello');
generic.add(true);
print(generic); // [6, 8.8, hello, true]
}
二.运算符
其中 + 、-、 *、 / 、||、 !、 && 、++、 – 、+=、-=、*=…这些同java 一样使用,其中特殊的赋值运算符中的 ??= (表示 变量如果原本无值及将右边值赋值于变量,如果变量原本有值就使用它原本的值)
void main(){
int time = 12;
int hour = 10;
hour ??= 18;
print(hour); // 10
int second ;
second ??= 60;
print(second); // 60
}
还有一个不同的是复合运算中的 ~/(取整)
void main(){
int time = 122;
int hour = 10;
print(time ~/ hour); // 12
}
三.条件表达式
1) 三目运算符: condition ? expression1 : expression2
2 ) ??运算符 expression1 ?? expression2 (如果expression1 不为空则取其值,反之取expression2的值)
void main(){
String goods = "apple";
String toolLearn;
String bag = goods ?? toolLearn;
print(bag); // apple
String grocery ;
String shop = "boxes";
String backpack = grocery ?? shop;
print(backpack); // boxes
}
四.控制语句
void main(){
String myHobby = "jog";
switch(myHobby){
case "game":
print("my hobby is game");
break;
case "jog":
print("my hobby is jog");
continue Prefer;
case "red":
print("my hobby is red");
break;
Prefer:
default:
print("I like study different languages, haha!");
}
// print out :
// my hobby is jog
// I like study different languages, haha!
}
五、 Function (方法)
1.
返回值类型 方法名 (参数1、参数2...){
方法体...
return 返回值
}
void main(){
String info = getPersonInfo('Lili','18'); // error: The argument type 'String' can't be assigned to the parameter type 'int'.
print(info);
}
String getPersonInfo (String name,int age){
return "This girl's name is $name,she is $age years old";
}
不指定参数类型也是被允许的
方法特性
1) 方法也是一个对象,并且具有具体类型 Function
2)返回值类型、参数类型都可以省略
3)箭头语法:=> expr 是{ return expr;} 的缩写 ,但是只适用于一个表达式
4)方法都有返回值。如果没有显示指定;它默认会在方法最后 return null
2. 方法中的可选参数
1)可选命名参数:{parm1, param2, …}
2)可选位置参数:[parm1,param2, …]
可选的命名参数在调用时必须加上参数名进行实参传递如:
void main(){
getPersonInfo('Lili'); // This girl's name is Lili, she is null years old and she lives in null
getPersonInfo('Lili',age: 18); // This girl's name is Lili, she is 18 years old and she lives in null
getPersonInfo('Lili',age: 18,addr: 'Chengdu, Sichuan, China'); // This girl's name is Lili, she is 18 years old and she lives in Chengdu, Sichuan, China
}
getPersonInfo ( String name, {int age ,String addr}) => print("This girl's name is $name, she is $age years old and she lives in $addr ");
3.默认参数值 (使用 ‘=’ 指定)
void main(){
getPersonInfo("Lili"); // This girl's name is Lili, she is 18 years old and she lives in Chengdu, Sichuan, China
}
getPersonInfo ( String name, [int age = 18 ,String addr = "Chengdu, Sichuan, China"]) => print("This girl's name is $name, she is $age years old and she lives in $addr ");
4.方法对象
1)方法可以作为对象赋值给其他变量
2)方法可以作为我参数传递给其他方法
void main(){
Function func = printPersonalInfo;
func(); // Hello world!
var studentList = ["Binbin","Tingting","Mingmint"];
// 将getEachFromList方法作为参数传递个forEach;进行元素打印
studentList.forEach(getEachFromList); // Binbin
// Tingting
// Mingmint
print(powerOperator(studentList,powerFn)); // [BinbinBinbinBinbin, TingtingTingtingTingting, MingmintMingmintMingmint]
}
printPersonalInfo() => print("Hello world!");
getEachFromList(val) => print(val);
powerOperator(List<String> list,String powerFn(str)){
for(var i =0;i< list.length; i++){
list[i] = powerFn(list[I]);
}
return list;
}
String powerFn(str) => str*3;
5. 匿名方法 (anonymous)
void main(){
var fn = (){
print("hello dart !");
};
fn (); // hello dart !
// 定义一个自动运行方法,同js (function($){}(window.document))()
((){
print("I am an automated methed!"); // I am an automated methed!
})();
var studentList = ["Binbin","Tingting","Mingmint"];
print(powerOperator(studentList,(str) => str * 3)); // [BinbinBinbinBinbin, TingtingTingtingTingting, MingmintMingmintMingmint]
}
printPersonalInfo() => print("Hello world!");
getEachFromList(val) => print(val);
powerOperator(List<String> list,String powerFn(str)){
for(var i =0;i< list.length; i++){
list[i] = powerFn(list[I]);
}
return list;
}
6. 闭包
理论:
1)闭包是一个方法(对象)
2)闭包定义在其它方法内部
3)闭包能够访问外部方法内的局部变量,并持有其状态
void main(){
var fnc = outsideFn();
fnc(); // 0
fnc(); // 1
fnc(); // 2
fnc(); // 3
fnc(); // 4
fnc(); // 5
}
outsideFn(){
int count = 0;
return (){
print(count++);
};
}
六. 面向对象
1 类、对象
先背一下对象和类的概念
对象:用来描述客观事物的一个实体,由一组属性和方法构成
对象的静态特征称为对象的属性(用来描述对象静态的特征的一个数据项)
对象的动态特征称为对象的方法(对象的行为)
类:定义了对象将会拥有的特征(属性)和行为(方法)
类属性:对象所拥有的静态特征在类中表示时称为类的属性(在类中定义对象的静态特征时)
类的方法:对象执行的操作称为类的方法
1) 使用 class 声明一个类(同 es6、java)
2) 使用关键字 new 创建对象(同 es6、java),new 可以省略
3) 所有对象都继承于Object类
属性与方法
1)属性默认会生成getter 和setter 方法
2)使用final申明的属性只有getter方法
3)属性和方法通过 . 访问
4)方法不能被重载 (这个和java不同)
void main(){
var person = Person();
person.name = "Wangxiaohu";
person.age = 13;
person.work(); // Wangxiaohu is a programmer, 13 years old this year, because he like to code very much ,so he is typing code!
}
class Person{
// 声明该类的属性(也称为实例变量)
String name;
int age;
void work(){
print("$name is a programmer, $age years old this year, because he like to code very much ,so he is typing code!");
}
//error: The name 'work' is already defined. (方法不能重置,因为已经定义)
// void work(int score){}
}
5)类及成员可见性
这个就没有了java 中的(public、private、protected、default)这四个修饰符了;
Dart 中的可见性以library(库)为单位
默认情况下,每一个Dart 文件就是一个库
使用 _ 表示库私有性(有点类似js 私有函数定义)
使用import 导入库
main.dart
import 'Person.dart';
void main(){
var person = Person();
person.name = "Wangxiaohu";
person.age = 13;
person.work(); // Wangxiaohu is a programmer, 13 years old this year, because he like to code very much ,so he is typing code!
}
Person.dart
class Person{
// 声明该类的属性(也称为实例变量)
String name;
int age;
void work(){
print("$name is a programmer, $age years old this year, because he like to code very much ,so he is typing code!");
}
//error: The name 'work' is already defined. (方法不能重置,因为已经定义)
// void work(int score){}
}
注意:Person.dart 中class Person 如果改为 class _Person 就变成了了私有了只有在当前的Person.dart文件中可以使用;对外不可见
2. 计算属性
1)计算属性的值是通过计算而来的,本身不存储值
2)计算属性赋值,是通过计算转换到其他实例变量
void main(){
var rect = new Rectangle();
rect.height= 20;
rect.width = 10;
print(rect.area); // 200
rect.area = 200;
print(rect.width); // 10.0
}
class Rectangle{
num width,height;
num get area => width * height;
set area(val) => width = val /20;
}
3. 构造方法
1)一个类没有显示指定 构造方法,则使用默认构造
2)如果显示指定了构造方法,默认构造方法将失效
3)构造方法不能被重载
void main(){
var person = new Person(); // 看这里就提示 error: 2 required argument(s) expected, but 0 found. 希望2个参数,但实际1个都没得
person.age = 18;
person.name = "Perpar";
}
class Person{
String name;
int age;
// 未显示指定构造,将使用默认构造如:
// Person(){
//
// }
// 如果显示指定构造,默认构造将无效 如:
Person(String name,int age){ // 也可以使用 dart语法糖 简写为 Person(this.name, this.age)
this.name = name;
this.age = age;
}
}
使用 dart 构造方法语法糖为final 属性赋值
void main(){
var person = new Person("jack");
print(person.name); // jack
}
class Person {
final String name;
// this.name会在构造方法执行之前进行参数赋值
Person(this.name);
}
命名构造方法
1) 使用 类名.方法 的形式来实现一个类多个构造方法
void main(){
var person = new Person("jack",18);
var person2 = new Person.withName("Pingping");
var person3 = new Person.withAge(19);
print(person.name); // jack
print(person2.name); // Pingping
print(person3.age); // 19
}
class Person {
final String name;
int age;
// this.name会在构造方法执行之前进行参数赋值
Person(this.name,this.age);
Person.withName(this.name);
Person.withAge(this.age);
}
4. 常量构造方法
1)如果类是不可变状态,就可以吧对象定义为编译时常量
2) 使用 const 声明构造方法,并且所有变量都为final
3)使用const 声明对象(可以省略)
使用场景:如果在开发过程中,我们想限制某个类实例化以后 它的 所有属性 只能被赋值一次,那设置const 就ok了
void main(){
const person = const Person("Lili", 18);
person.study(); // I am reading the JAVA programming ideas here!
}
class Person {
final String name;
final int age;
// 属性会在构造方法执行之前进行参数赋值
const Person(this.name,this.age);
study(){
print("I am reading the JAVA programming ideas here!");
}
}
5. 工厂构造方法
1) 工厂构造方法类似与设计模式的工厂模式
2) 在构造方法前使用factory 关键字来创建一个工厂构造方法
3) 在工厂构造方法中可以返回一个对象
void main() {
var factoryConstruct = Logger("firstLog");
factoryConstruct.printLog("Hi, hello I am coming to the factory !");
}
class Logger{
final String name;
static final Map<String,Logger> _cache = <String,Logger>{};
/**
* 使用工厂构造方法 根据 传入的 name 到_cache map中查找如果存在就返回;
* 如果不存在就调用_internal对name进行赋值,同时将该构造缓存与_cache中,
* 同时将其返回给调用者
*/
factory Logger(String name){
if(_cache.containsKey(name)){
return _cache[name];
}else{
final logger = Logger._internal(name);
_cache[name] = logger;
return logger;
}
}
Logger._internal(this.name); // 一个私有的内部构造方法
printLog(String msg) => print(msg); // Hi, hello I am coming to the factory !
}
6. 初始化列表
1)初始化列表会在构造方法执行之前执行
2)使用逗号分隔初始化表达式
3)常用于对final 变量赋值
void main(){
var map = {"name":"Lili","age":18,"addr":" Chengdu, Sichuan, China"};
var person = new Person(map);
person.sayInfo(); // Hello, Everybody; my name is Lili, I am 18 years old this year, I come from Chengdu, Sichuan, China
}
class Person{
final String name;
final String addr;
int age;
// 使用 初始化列表为final 属性赋值
Person(Map map):name = map["name"],addr = map["addr"]{
age = map["age"];
}
sayInfo(){
print("Hello, Everybody; my name is $name, I am $age years old this year, I come from $addr");
}
}
7. 静态成员
1)使用static关键字来实现类级别的变量和函数
2)静态成员不能访问非静态成员,非静态成员可以访问静态成员
3)类中的常量需要使用static const 进行声明
void main(){
var person = new Person();
Person.work(); // I earned a thousand yuan for my work,so I saved 100 yuan,Now the total deposit is ¥20100.0 。
person.shop(); // I went to the store and bought a dress and used 100 yuan,so now the total deposit is ¥19100.0
}
class Person{
// 类里面声明常量需要使用 static const
// const String hobby="jog"; // error: Only static fields can be declared as const.
static const String hobby = "jog";
double salaries = 1000.00;
static double deposit = 20000.00;
static work(){
// salaries += 120.00; // 静态成员不能访问非静态成员(double salaries为非静态属性,是实例对象的一个属性)error: Instance members can't be accessed from a static method.
deposit += 100.00;
print("I earned a thousand yuan for my work,so I saved 100 yuan,Now the total deposit is ¥$deposit 。");
}
shop(){
deposit -=1000.00; // 非静态成员可以访问静态成员
print("I went to the store and bought a dress and used 100 yuan,so now the total deposit is ¥$deposit");
}
}
8. 对象操作符
1) 条件成员访问 : ?.
void main(){
Person person;
person?.work(); // 如果实例为空就不向后执行【该操作符可以避免对象空指针的问题】
person?.name; // 同上
// person.name; // Unhandled exception: NoSuchMethodError: The getter 'name' was called on null. Receiver: null
Person person2 = Person();
person2.work(); // I am working in the company
}
class Person{
String name;
int age;
work(){
print("I am working in the company");
}
}
2)类型转换 :as
3)是否指定的类型:is 、is!
void main(){
var person ;
person = "";
// person.work(); //该person是个字符串类型没有实例方法work Unhandled exception: NoSuchMethodError: Class 'String' has no instance method 'work'.
// (person as Person).work(); // string 类型不能转为Person Unhandled exception:type 'String' is not a subtype of type 'Person' in type cast
person = Person();
// 是is 关键字进行类型判断 (如同java 的 instanceOf); 反之使用 is! 关键字判断不是 该类型
if(person is Person){
person.work(); // I am working in the company
}
}
class Person{
String name;
int age;
work(){
print("I am working in the company");
}
}
4)级联操作 : ..
void main(){
// 和 build 设计模式 很类似
var person = new Person();
person .. name = "Lili"
..age = 18
..work(); // I am Lili,I am 18 years old.
// 也可以使用这种匿名对象的方式
new Person()..name = "Tingting"
..age = 19
..work(); // I am Tingting,I am 19 years old.
}
class Person{
String name;
int age;
work(){
print("I am $name,I am $age years old.");
}
}
9. 对象的call 方法
dart 中 方法可以作为对象来使用,对象也可以作为方法来使用
1)如果类实现了call() 方法,则该类的对象可以作为方法使用
void main(){
var person = new Person();
print(person("Tingting",18)); // I am Tingting,I am 18 years old.
}
class Person{
String name;
int age;
// 该对象实现了call 后,他的实例就可以当成方法来使用了
String call(String name,int age){
return "I am $name,I am $age years old.";
}
}
七、 面向对象高级扩展
面向对象三大特性(和java一样):封装、继承、多态
1)继承,继承中的构造方法(extends)
2)抽象类(abstract)
3)接口(interface)
4)Mixins(这个同vue的mixin类似),操作符的覆写
1. 继承(extends)
1)使用extends 关键字继承一个类
2)子类会继承父类可见的属性和方法,不会继承构造方法
3)子类能够覆写父类的方法,getter和setter
4)和java一样一个子类只能继承一个父类,同样使用继承能实现多态的特性
未完待续...
'
image.png
网友评论