Flutter - 入门

2021-03-27  本文已影响0人  Codepgq

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、数组(列表)、集合等数据。

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

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

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

字符串可以用 + 号连接

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
}
常用操作符

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 标记是异步方法
// {}内部就是函数体

类、接口、继承

接口

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包中,其中

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);
});

异步

扩展方法

和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()));  
上一篇 下一篇

猜你喜欢

热点阅读