Flutter - 入门

Dart基础

如果你有JSJavaKotlinSwift等语言的基础,入门几乎没啥子难度

程序入口

dartmain函数开始运行,国际惯例

void main() {
    print("Hello World!");
}

由于dart中没有privatepublic等修饰符,所以约定俗成下划线开头表示私有。

下面用一个类的声明讲解

/// 声明
class Hello {

    /// 私有变量
    String _privateName = "私有名称";
    
    /// 公开变量
    int age = 18;
    
    /// 私有方法
    _privateFunction() { 
        print("1");
    }
    
    /// 公开方法
    publicFunction() {
        print("1");
    }
    
    @protected
    refresh() {
        
    }
}       

setter/getter

double _progress;

double get progress => _progress;

set progress(double newValue) {
    /// 自己的逻辑处理
    _progress = newValue;
}

final/const

两者都是声明常量使用,区别是一个是在编译期,一个是运行期。

import

用于导入某些具体类/第三方SDK的实现

基础数据类型

dart支持数字、字符串、bool、数组(列表)、集合等数据。

数字
  • int取值区间在-2^{53} ~ 2^{53}

  • double类型为64位的双精度浮点型

方法 含义
isFinite 是否为有限数字
isInfinite 是否是无穷大
isNan 是否是数字
isNegative 是否为负数
sign 如果数字小于0,返回-1;大于0返回1,如果本身是Nan或者0,返回0
isEven 是否是偶数
isOdd 是否是奇数
abs 绝对值
ceil 返回不小于该数字的最小整数
floor 返回不大于当前数字的最大整数
round 返回最接近当前数字的整数
toDouble 转化为double类型
字符串

字符串可以用""表示也可以用''表示。

在字符串中引用其他的变量

  • 成员变量

    "print("age is $age");"

  • 成员变量的成员变量、或者其他表达式

    print("name is ${jack.nickName}");

字符串可以用 + 号连接

bool

dart中的if只支持bool只,不支持判空处理

String g = null;

/// 不合法
if (g) {}

/// 合法
if(g!=null) {}
集合(列表)
  • 有序
  • 可重复
List list = [1,2,3,4,5, "6"]; 未指定的类型的情况下,可以插入任意值
List<String> strList = ["a", "b", "c"]; // 指定类型的情况只能插入该类型的值
List list2 = [-1, 0, ...list];

List list3 = null;
List list4 = [10, 11, ...?list3];
方法 说明
generate 根据数据创建一个表
length 列表长度
sort 排序,根据传入的compare判断条件
indexOf 获取下表,根据传入的条件,正序遍历找到就返回
lastIndexWhere 从后向前遍历,根据传入条件找到第一个返回并结束
Set 集合
  • 无序
  • 不可重复
Set<String> name = {"Jack", "Mark"};
name.add("Lucky");
方法 说明
lookup 查找某个元素
contains 是否包含某个值
difference 两个集合进行比较,返回不同的元素
Map

键值对的方式进行数据的存储,键唯一,值可以不唯一。

未指定value的类型情况下,值可以是任意类型

Map map = {
    "age": 19,
    "name": "Hello",
    "info": {}
};

//add
map['address'] = "";

//put
String name = map['name'];
方法 说明
putIfAbsent 根据传入的key查看值是否存在,存在就返回,不存在就插入在返回
isEmpty 是否为空
isNotEmpty 是否不为空
length 返回map的长度
containsKey 是否包含某个key
containsValue 是否包含某个value
enum

枚举,这里枚举值的类型是int,默认从0开始,并且不可以设置起始值

enum Style {
    normal,
    vip
}
常用操作符
  • ..

    联级操作符

    Object obj = Object();
    obj
      ..name=""
      ..age=18
      ..address = "";
    
  • ??

    判断前面的值/对象是否为空,为空就是用??后面的值

    int a = null;
    int b = 1;
    print("${a ?? "hello"}"); // hello
    print("${b ?? "hello"}"); // 1    
    
  • ??=

    判断是否已经初始化

    int a = 2;
    a ??= 3;
    print("$a"); // 2, 如果是 int a = null; 那么结果就是 3
    
  • ~/

    整除

    print("${5.2 ~/ 3.3 }"); // 1
    

var和dynamic

var会自动推导出类型,var只是语法糖,运行的时候会根据值推到类型

dynamic表示动态类型,不做任何检测,真正的动态类型

函数方法

dart中的函数声明格式为返回值 函数名(参数列表) 修饰符{ 函数体}

int test(int age, {String name, String address}) async {
     await Future.delay(Duration(seconds: 1));
   return 1;
}

// int 返回值类型
// test 函数名称
// int age 参数(必填,且顺序固定
// String name 参数 (非必填,顺序不要求
// String address 参数 (非必填,顺序不要求
// async 标记是异步方法
// {}内部就是函数体

类、接口、继承

  • abstract class 接口类

    内部的函数只用声明就够了

  • class

    内部的函数需要实现

接口

dart中没有接口关键字,类也可以作为接口,只需要使用implements实现就好

继承

extends,使用这个修饰。

demo
abstrace class Interface {
    void doA();
    void doB();
}

class InterfaceClass {
    void doC() {}
    void doD() {}
}

class Demo implements Interface, InterfaceClass {
    void doA() {}
    void doB() {}
    void doC() {}
    void doD() {}
}

mixins

混入,混入是的基础顺序是从右到做依次执行,也就是说最后混入的类,如果遇到同名函数,最优先执行,而且和super方法是否执行有关。

异常

通过try..catch捕获异常,通过throw抛出异常

异常类型 说明
FormatException 当字符串或某些其他数据没有预期格式,且无法解析活处理时抛出
IntergerDivisionByZeroException 当数字除与0的时候抛出
IOException 输入、输入相关的异常
IsolateSpawnException 无法创建隔离时抛出
Timeout 等待异步结果是,如果发生超时,则抛出

Isolate

Dart本身是单线程执行,但还是增加了Isolate提供跨线程的真异步操作。因为在dart线程中不会共享内存,所以也不会存在死锁,从而而导致了Isolate之间的数据只能通过port的端口方式发送接口,所以Isolate也称之为隔离的执行。Dart中提供了Isolate的封装,便于我们使用

Isolate主要在 dart:isolate包中,其中

  • Isolate用于dart执行上下文隔离
  • ReceivePort和SendPort一起,是通信的唯一方式
  • SendPort将消息发送到其他ReceivePort
demo
Isolate isolate;
void doIsolate() async {
  var receive = ReceivePort();
  isolate = await Isolate.spawn(echoResult, receive.sendPort);
  receive.listen((message) { 
    print("message is $message");
  });
}

/// 处理消息
void echoResult(SendPort port) {
  final msg = "Hello world";
  Timer.periodic(const Duration(seconds: 1), (timer) { 
    port.send(msg);
  });
}

void kill() {
  isolate.kill(priority: Isolate.immediate);
  isolate = null;
}

除了这以外,还提供了一个更为简单的处理方法compute。需要注意的是compute方法运行中的方法必须是顶级方法或者静态方法

testCompute() {
  compute(execString, "hello").then((value) {
    print("isolate compute $value "); ///isolate compute hello world
  });
}

/// 此为顶级函数
Future execString(value) async {
  await Future.delayed(Duration(milliseconds: 1000));
  return value + " world";
}

Zone

表示Dart运行的环境,类似于一个沙盒。通过Zone我们还可以监听到全局范围内捕获到的异常

runZoned(() {
    runApp(FlutterApp());
}, onError: (Objects obj, StackTrace stack) {
    print(obj);
    print(stack);
});

异步

  • async/await
  • Stream

扩展方法

和swift一样,可以对原有类进行扩展

demo
extension ExtendsFun on String {
    int parseToInt() {
        return int.tryParse(this);
    }
}

main() {
    String num = "4";
    print(  num.parseToInt()); // 4
}

常用控件

Flutter中的Widget可以分为两类,StatelessWidgetStatefulWidget。分表表示无状态和有状态的Widget

两者都是通过widget.build方法构建UI,不同之处StatefulWidget可以进行刷新操作,生命周期也略有不同。

具体的类型控件自行查阅相关文档

列举一些常用的Widget

控件 描述
Container 只有一个子Widget、默认充满,是一个集合了很多属性的容器视图,包含了:padding、margin、color、width、height、decoration等
Padding 只有一个子Widget,只包含Padding的设置。多用于控制边距
Center 只有一个子Widget,被其包起来的Widget会居中显示
Stack 有多个子Widget,是一个列表,列表末尾的child会显示在最顶层
Column 有多个子Widget,是一个列表,默认是从屏幕上至下,垂直排列
Row 有多个子Widget,是一个列表,默认是从屏幕左至右,水平排列
Expanded 只有一个子Widget,在Column和Row中撑满余下空间,如果要均分,可以设置其的flex属性
ListView 和Column类似,区别之处就是可以超出屏幕范围,加载也会根据屏幕显示区域进行处理

UI更新

在实际开发中我们推送尽可能的使用StatelessWidget,但是由于它是无状态的,所以就针对他的刷新机制推出了很多实现方案:Reduxproviderblocprovide。这里推荐使用官方推崇的Provider

StatefulWidget的生命周期

生命周期

路由跳转

使用路由跳转时候可以使用pushName或者push方法,两个都可以进行导航操作;如果使用pushName,在必须在根App处进行定义,使用Push则没有这方面的要求

demo
class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
        return MaterialApp(
            home: HomePage(),
            routes: {
            "weather": (_) => WeatherPage(),
            }
        );
    }
}

// pushName
Navigator.pushName(context, 'weather');

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

推荐阅读更多精彩内容