Flutter学习记录-起步

2020年初的新冠肺炎到现在还在全球肆虐,给全球的上空蒙上了一层厚厚的阴影,希望疫情能早点结束,大家回归平静生活。

2019年5G的到来和新冠肺炎给我们提了个醒,我们处在一个飞速发展和剧烈变化的时代,为了不被时代抛弃只能紧跟时代的脚步向前。近年来一直在想未来的移动端出路何在,2019年的中美贸易战让我们看到了有个流氓国家的流氓行为,导致华为公司不能继续使用Google的一些服务,这就导致华为只能自己开发一套。虽然这些看起来离我们很远,如果有一天华为真的不能使用Android了而且华为占据Android市场这么大的份额,肯定会有自己的开发平台及系统。这样就又让我们一线开发人员更加看不明白未来的走向。不过生活还要继续,脚步不能停下来,让我们继续前行。


接上一章开篇继续

Flutter简介

这里引用书中的介绍:

Flutter 是 Google推出并开源的移动应用开发框架,主打跨平台、高保真、高性能。开发者可以通过 Dart语言开发 App,一套代码同时运行在 iOS 和 Android平台。 Flutter提供了丰富的组件、接口,开发者可以很快地为 Flutter添加 native扩展。同时 Flutter还使用 Native引擎渲染视图,这无疑能为用户提供良好的体验。

发展时间:

2017 年 Google I/O 大会上,Google 首次推出了一款新的用于创建跨平台、高性能的移动应用框架——Flutter。
2018年2月,Flutter发布了第一个Beta版本,同年五月, 在2018年Google I/O 大会上,Flutter 更新到了 beta 3 版本。
2018年6月,Flutter发布了首个预览版本,这意味着 Flutter 进入了正式版(1.0)发布前的最后阶段。

到现在Flutter在Github上的Star已经超过了90k,可见它的受欢迎程度。还有它具有的一些特点如:跨平台自绘引擎、高效率,这些大家都可以从书中获取,我就不在此重复了。由于我们是初学Flutter,对于一些概念不是很明确,不过我觉得可以先不纠结这些概念,先往下走,登学过一边之后再回过头来看,应该就能明白这些概念说的是什么了。

看下Flutter的的框架结构图:
Flutter框架结构

这是一个纯 Dart实现的 SDK,它实现了一套基础库,自底向上,我们来简单介绍一下:
底下两层(Foundation和Animation、Painting、Gestures)在Google的一些视频中被合并为一个dart UI层,对应的是Flutter中的dart:ui包,它是Flutter引擎暴露的底层UI库,提供动画、手势及绘制能力。
Rendering层,这一层是一个抽象的布局层,它依赖于dart UI层,Rendering层会构建一个UI树,当UI树有变化时,会计算出有变化的部分,然后更新UI树,最终将UI树绘制到屏幕上,这个过程类似于React中的虚拟DOM。Rendering层可以说是Flutter UI框架最核心的部分,它除了确定每个UI元素的位置、大小之外还要进行坐标变换、绘制(调用底层dart:ui)。
Widgets层是Flutter提供的的一套基础组件库,在基础组件库之上,Flutter还提供了 Material 和Cupertino两种视觉风格的组件库。而我们Flutter开发的大多数场景,只是和这两层打交道。

以上是让大家对Flutter有个大致的印象,相信大家对Flutter有个一个初步印象。由于Flutter是采用Dart语言开发,我们还需要对Dart语言有个基本的了解。
Dart是个强类型的语言,借鉴了Java和JavaScript的经验,如果你接触过这两种语言,那会非常容易上手Dart,下面来看看Dart语言的基础用法。

1、变量声明

var
可以接收任何类型的变量,但是一旦被变量赋值,那么就不能再改变为其他类型。
例子:
var s;
s = “hello world”;
代码到这是没有问题的,如果加上下面一行则会报错。
s = 1000;
因为变量“s”已经被赋值为string类型,再次赋值为int类型则会报错。

dynamic和Object
object是所有对象的根基类,所有的类型都是object的子类,所以任何类型的的数据都可以赋值给object。dynamic和object作为声明变量的关键词时,变量可以随便更改类型而不会报错。如:
dynamic x;
ocject y;
x = “hello world”;
y = 1000;
上面是第一次给两个变量赋值。下面还可以随便更改两个变量的类型。
x = 1000;
y = “hello world”;
而dynamic和object的不同就在于,dynamic声明的对象编译器会提供所有可能的组合,而object声明的对象只能使用object的属性和方法。
这个地方书上写的暂时还不太清楚,等学习到后面看看能不能搞明白。

final和const
如果你从未打算更改一个变量的值,那么使用final和const来声明。使用这两个关键词声明变量的时候可以省略变量的类型。如:
final str1 = “hello”;
final str2 = “world”;
这两个的区别按我的理解就是:final在程序第一次运行的时候就初始化了,而const是在使用的时候才初始化。

2、函数

函数声明

Dart是一种真正的面向对象的语言,所以即使是函数也是对象,并且有一个类型Function。这意味着函数可以赋值给变量或作为参数传递给其他函数,这是函数式编程的典型特征。

一个基础的函数声明:
声明了一个返回值为bool类型的名字为isNull的用来判断传递的数据是否为null的函数

 bool isNull(String data){
    return data == null;
  }

如果函数没有返回值,则默认为dynamic处理。
对于只包含一个表达式的函数,可以简写为:

printData(String data) => printData(data);

函数作为变量,这里引用书中代码,自己看的还不是很明白。

var say = (str){
  print(str);
};
say("hi world");

函数作为参数传递,这里引用书中代码,自己看的还不是很明白。

void execute(var callback) {
    callback();
}
execute(() => print("xxx"))

可选位置参数,这个很简单,用[]标记为可选的位置参数,放在参数列表的最后面,代表这个参数可传可不传,看下书中例子:

String say(String from, String msg, [String device]) {
  var result = '$from says $msg';
  if (device != null) {
    result = '$result with a $device';
  }
  return result;
}

两次调用的结果:

say('Bob', 'Howdy'); //结果是: Bob says Howdy
say('Bob', 'Howdy', 'smoke signal'); //结果是:Bob says Howdy with a smoke signal

可选命名参数,定义函数时,使用{}包裹参数,放到参数列表最后面,用于指定命名参数,这里面的参数可以选择性的传,可以传1个也可以传2个。看例子:

void setBG({Colors colors,bool hidden}){
    //TODO 省略代码
  }
setBG(Colors.red);

可选命名参数在Flutter中使用非常多,常见于组件的定义。

3、异步支持

Dart类库有非常多的返回Future或者Stream对象的函数。 这些函数被称为异步函数:它们只会在设置好一些耗时操作之后返回,比如像 IO操作。而不是等到这个操作完成。
async和await关键词支持了异步编程,允许您写出和同步代码很像的异步代码。
Future
表示一个异步操作的最终完成(包括成功或者失败),且Future所有的API返回仍然是一个Future对象,方便链式调用。以下是常用几个API:

Future.then:表示接收异步操作的结果,见代码:

Future.delayed(new Duration(seconds: 2),(){
   return "hi world!";
}).then((data){
   print(data);
});

Future.catchError或者Future.onError:表示接收异步发生的错误,见代码:

Future.delayed(new Duration(seconds: 2),(){
   //return "hi world!";
   throw AssertionError("Error");  
}).then((data){
   //执行成功会走到这里  
   print("success");
}).catchError((e){
   //执行失败会走到这里  
   print(e);
});

Future.delayed(new Duration(seconds: 2), () {
    //return "hi world!";
    throw AssertionError("Error");
}).then((data) {
    print("success");
}, onError: (e) {
    print(e);
});

Future.whenComplete:表示无论成功失败都会执行的,见代码:

Future.delayed(new Duration(seconds: 2),(){
   //return "hi world!";
   throw AssertionError("Error");
}).then((data){
   //执行成功会走到这里 
   print(data);
}).catchError((e){
   //执行失败会走到这里   
   print(e);
}).whenComplete((){
   //无论成功或失败都会走到这里
});

Future.wait:接收一个Future数组,用来执行数组中的所有异步任务,所有的任务执行成功才会执行then的回调,否则只要又一个异步任务执行失败则执行catchError回调,见代码:

Future.wait([
  // 2秒后返回结果  
  Future.delayed(new Duration(seconds: 2), () {
    return "hello";
  }),
  // 4秒后返回结果  
  Future.delayed(new Duration(seconds: 4), () {
    return " world";
  })
]).then((results){
  print(results[0]+results[1]);
}).catchError((e){
  print(e);
});

Async/await:用于解决回调地狱,用法和JavaScript一模一样。
在以前的java代码中会出现一种情况就是回调用套用回调的情况,这就是回调地狱。Async/await
就是为了解决这个问题出现的。我们看下对比的代码:
这是回调中套用回调的情况,代码的阅读性极低且极难维护:

login("alice","******").then((id){
 //登录成功后通过,id获取用户信息    
 getUserInfo(id).then((userInfo){
    //获取用户信息后保存 
    saveUserInfo(userInfo).then((){
       //保存用户信息,接下来执行其它操作
        ...
    });
  });
})

以下是用Async/await解决后的代码:

task() async {
   try{
    String id = await login("alice","******");
    String userInfo = await getUserInfo(id);
    await saveUserInfo(userInfo);
    //执行接下来的操作   
   } catch(e){
    //错误处理   
    print(e);   
   }  
}

async用来表示函数是异步的,定义的函数会返回一个Future对象,可以使用then方法添加回调函数。
await 后面是一个Future,表示等待该异步任务完成,异步完成后才会往下走;await必须出现在 async 函数内部。
Stream
是用于接收异步事件的数据,与Future不同的是,Future只有在执行完任务后才会有数据,而Stream可以接收多个异步任务的结果,也就是说在执行异步任务时,可以多次触发任务的成功或失败。多用于网络下载、文件读写。看例子:

Stream.fromFutures([
  // 1秒后返回结果
  Future.delayed(new Duration(seconds: 1), () {
    return "hello 1";
  }),
  // 抛出一个异常
  Future.delayed(new Duration(seconds: 2),(){
    throw AssertionError("Error");
  }),
  // 3秒后返回结果
  Future.delayed(new Duration(seconds: 3), () {
    return "hello 3";
  })
]).listen((data){
   print(data);
}, onError: (e){
   print(e.message);
},onDone: (){

});

上面的代码会依次输出:

I/flutter (17666): hello 1
I/flutter (17666): Error
I/flutter (17666): hello 3

以上就是Flutter的简单介绍和Dart语言的简单介绍,我只是对此有个简单的了解,很多知识不是很清楚,还得需要后续的学习来逐渐认清这些知识和熟练掌握它们。
下一章就要学习Flutter的环境搭建了,这个应该不是难,毕竟只是使用工具的技能。

发布了6 篇原创文章 · 获赞 1 · 访问量 442

猜你喜欢

转载自blog.csdn.net/qq_35809004/article/details/105557005