flutter学习笔记

声明:以下内容绝大部分参考以下这本书,谢谢作者分享

  • flutter中文网

1、当然,如果你是iOS开发者,也不用担心,Dart中也有一些与Swift比较相似的特性,如命名参数等,笔者当时学习Dart时,只是花了一个小时,看完Dart官网的Language Tour,就开始动手写Flutter了。
2、新东方、咸鱼、字节跳动都用了flutter
3、选择那个…控件后,试了几次成功了,download 失败,直接输入也失败
4、工程拿出来有bug
5、Object 是Dart所有对象的根基类,也就是说所有类型都是Object的子类(包括Function和Null),所以任何类型的数据都可以赋值给Object声明的对象. dynamic与var一样都是关键词,声明的变量可以赋值任意对象。 而dynamic与Object相同之处在于,他们声明的变量可以在后期改变赋值类型。
6、dynamic与Object不同的是,dynamic声明的对象编译器会提供所有可能的组合, 而Object声明的对象只能使用Object的属性与方法, 否则编译器会报错。
7、dynamic的这个特性与Objective-C中的id作用很像. dynamic的这个特点使得我们在使用它时需要格外注意,这很容易引入一个运行时错误.
8、Dart是一种真正的面向对象的语言
9、所以即使是函数也是对象,并且有一个类型Function。这意味着函数可以赋值给变量或作为参数传递给其他函数,这是函数式编程的典型特征。
10、Dart函数声明如果没有显式声明返回值类型时会默认当做dynamic处理
11、bool isNoble (int atomicNumber)=> _nobleGases [atomicNumber] != null
对于一个包含一个表达式的函数,可以使用简写语法
12、包装一组函数参数,用[]标记为可选的位置参数,并放在参数列表的最后面:
String say(String from, String msg, [String device]){
var result = ‘$from says KaTeX parse error: Expected '}', got 'EOF' at end of input: … result = ‘result with a $device’;
}
return result;
}
13、定义函数时,使用{param1, param2,….},放在参数列表的最后面,用于指定命名参数,例如:
1.4.3
Dart 类库有非常多的返回Future或者Stream对象的函数。这些函数被称为异步函数:它们只会设置好一些耗时操作之后返回,比如像IO操作。而不是等到这个操作完成。
async 和await关键词支持了异步编程,允许您写出和同步代码很像的异步代码
1.4.4 Stream 也是用于接收异步事件的数据,和Future不同的是,它可以接收多个异步操作的结果(成功或失败)。也就是说,在执行异步任务时,可以通过多次触发成功或失败事件来传递结果数据或错误异常。
1.4.5
但笔者相信,随着Flutter的逐渐火热,会回过头来反推Dart生态加速发展,对于Dart来说,现在需要的是时间。
1.4.6
所以单从这一点来看,Dart并不具备什么明显优势,但综合起来看,Dart既能进行服务端脚本、APP开发、web开发,这就有优势了!
1.4.7
笔者还是很看好Dart语言的将来,之所以表这个态,是因为在新技术发展初期,很多人可能还有所摇摆,有所犹豫,所以有必要给大家打一剂强心针,当然,这是一个见仁见智的问题,大家可以各抒己见。
1.4.8
flutter build apk 这个命令要在根部执行
1.4.9 flutter build ios —release 不行
添加这个就行了
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
很奇怪,不是昨天就在的吗
1.5.0
dart framework:
Material , Cupertino, Widgets, Rendering, Animation, Painting, Gestures, Foudation
其中:Material 是一种标准的的移动端和web端的视觉设计语言,Flutter默认提供了一套丰富的Material风格的组件
1.5.1
Everything’s a Widget
每件事都是一个小部件

1.6 widget 学习

flutter学习笔记_第1张图片

  • Flutter快速上车之Widget

  • 1.6.1
    Flutter的设计思想就是完全的widget化

  • 1.6.2
    Flutter的设计思想就是完全的widget化

  • 1.6.3
    Decoration 是对container 进行装饰的描述

  • 1.6.4
    flutter 官方也意识到了这个问题,他们从实际编写效率的角提供了一个友好高效的封装,这就是Container

  • 16.5
    Decoration是对Container进行装饰的描述。其概念类似与android中的shape。一般实际场景中会使用他的子类BoxDecoration。BoxDecoration提供了对背景色,边框,圆角,阴影和渐变等功能的定制能力。

  • 16.6

路由管理

  • 1.7.1
    路由在移动开发中通常指页面(page) ,这跟web开发中单页应用的Route概念意义是相同的,Route在Android中通常指一个Activity,在iOS中指一个ViewController,所谓路由管理,就是管理页面之间如何跳转,通常也可被称为导航管理。Flutter 中的路由管理和原生开发类似,无论是android 还是iOS,导航管理都会维护一个路由栈,路由入栈(push)操作对应打开一个新页面,路由出栈(pop)操作对应页面关闭操作,二路由管理主要是指如何来管理路由栈。
  • 1.7.2
    MaterialPageRoute
    MaterialPageRoute 继承自PageRoute 类,PageRoute类是一个抽象类,表示占有整个屏幕空间的一个模态路由页面,它还定义了路由构建及切换时过度动画的相关接口及属性。

继承关系extends

  • 使用关键字extends继承一个类
  • 子类会继承父类可见的属性和方法,不会继承构造方法
  • 子类能够复写父类的方法,getter和setter
  • 单继承,多态性

pub 仓库

  • 上文所述的依赖方式是依赖Pub仓库的。但我们还可以依赖本地包和git仓库。
  • 依赖git ,你也可以依赖存储在git仓库中的包。例如
dependencies:
  pkg1:
    git:
      url: git://github.com/xxx/pkg1.git
  • 上面的嘉定包位于git存储库的根目录中,如果不是这种情况,可以使用path参数指定相对位置,例如:
dependencies:
  package1:
    git:
      url: git://github.com/flutter/packages.git
      path: packages/package1

资源管理

  • 常见类型的assets包括静态数据(例如json文件)、配置文件、图标和图片(JPEG,webp,gif,动画webp/gif,png,bmp,和wemp)等
  • assets 指定应包含在应用程序中的文件,每个asset都通过相对于pubspec.yaml文件所在的文件系统路径来标识自身的路径。
  • asset的声明顺序书无关紧要的,asset 的实际目录可以是任务文件夹
  • 那么两个graphics/background.png和graphics/dark/background.png都包含在您的asset bundle 中,前者被认为是 main asset(主资源),后者被认为是一种变体(variant)

调试工具

  • 在运行应用程序前,请运行flutter analyze 测试你的代码。这个工具是一个静态的检查工具。
  • 一个中间模式可以关闭除Observatory 之外所有调试辅助工具的,称为’profile mode’,用–profile 替代 --release即可。
  • 这里面有很多工具,细细品读

异常捕获和线程模型

  • 在java和oc中,如果程序发生异常且没有被捕获,那么程序会终止,但是这在dart或者javascript中则不会。
  • java和oc都是多线程模型的编程语言,任意一个线程触发异常且该异常未被捕获时,就会导致整个进程退出。但是dart和javascript不会,它们是单线程模型,运行机制很相似。
  • Dart在单线程中是以消息循环机制来运行的,其中包含两个任务队列,一个是“微任务队列”microtask queue,另一个叫做"事件队列"event queue.微任务队列的执行优先级别高于事件队列。
  • 如果微任务太多,执行时间总和就越久,事件队列任务的延迟也就越久,对于GUI应用来说最直观的表现就是比较卡,所以必须得保证微任务队列不会太长。
  • 在事件循环中,当某个任务发生异常并没有被捕获时,程序并不会退出,而直接导致的结果是当前任务的后续代码就不会被执行了,也就是说一个任务中的异常是不会影响其它任务执行的。
  • Dart中可以通过try/catch/finally来捕获代码块异常

Widget 简介

  • 与原生开发中的"控件"不同的是,Flutter中的Widget的概念更广,它不仅可以表示UI元素,也可以表示一些功能性的组件如: 用于手势检测的GestureDectector Widget ,用于App主题数据传递的Theme等等
  • 在flutter 中,Widget的功能是继承DiagnosticableTree,是诊断树。

Widget状态管理

  • 在widget内部管理状态封装性会好一些,而父Widget中管理会比较灵活,有些时候,如果不确定到底怎么管理状态,那么推荐的首选是在父widget中管理(灵活会显得更重要一些)
  • StatelessElement 用于不需要维护状态的场景,它通常在build方法中通过嵌套其它Widget来构建UI,在构建过程中递归的构建其嵌套的Widget。
  • class _MyHomePageState extends State
    这么写的目的是什么,告诉这个方法是交给谁来用的,去掉也能跑。
 setState() {
      _counter++;
    };
 setState(() {
      _counter++;
    });

这两种写法只有第二种方法才是正确的,第一种方法不行的。

TextSpan

  • 在上面的例子中,Text的所有文本内容只能按同一样式,如果我们需要对一个Text的内容的不同部分按照不同的样式显示,这时就可以使用TextSpan,它代表文本的一个"片段"

DefaultTextStyle

  • 文本的样式默认是可以被继承的(子类文本类组件未指定具体样式时可以使用Widget树中父级设置的默认样式)

输入框和表单

  • controller 编辑框的控制器,通过它可以设置/获取编辑框的内容,选择编辑内容,监听编辑文本改变事件。大多数情况下我们都提供一个controller来与文本框交互。如果没有 提供controller,则TextField内部会自动创建一个。
  • FLutter 提供了一个form组件,它可以对输入框进行分组,然后进行一些统一操作,如输入内容检验、输入框重置以及输入内容保存。
  • From继承自Statefulwidget对象,它对应的状态类为FormState.

container

  • 可以发现,直观的感觉就是margin的留白是在容器外部,而padding的留白是在容器内部,读者需要记住这个差异。

Center

  • Creates a widget that centers its child
    让这个widget在它的孩子中间,换句话说,孩子也在这个widget中间。
  • 其实大多数时候,我们是不需要关心key对,但是如果我们需要对处于某种状态的相同类型的控件集合进行添加,删除或重新排序时,我们就需要用到key了

Flex

源码简单的令人发指,只有三个传值,这里我们只关注两个:

  • flex
  • child
    展开[row],[Column]或[Flex]的子代的小部件

层叠布局

  • Flutter中使用Stack和Positioned这两个组件来配合实现绝对定位
  • 层叠布局和Web中的绝对定位、Android中的Frame布局是相似的,子组件可以根据距父容器四个角的位置来确定自身的位置。

Stack

  • fit:此参数用于确定没有定位的子组件如何去适应Stack的大小。StackFit.loose表示使用子组件的大小,StackFit.expand表示扩伸到Stack的大小。
  • overflow:此属性决定如何显示超出Stack显示空间的子组件;值为Overflow.clip时,超出部分会被剪裁(隐藏),值为Overflow.visible 时则不会。
  • InheritedWidget是Flutter中非常重要的一个功能型组件

构造函数

  • 如果未声明构造函数,则会提供默认构造函数。 默认构造函数没有参数,并在调用父类无参数构造函数。
  • 子类不能继承其父类构造函数,一个没有声明构造函数的子类只有默认(无参数,无名称)构造函数
  • 如果父类没有未命名的无参数构造函数,则必须手动调用父类中的一个构造函数。 在子类的构造函数体之后用冒号(:)指定父类构造函数

代码执行顺序

  • 初始化列表
  • 父类的无参数构造函数
  • 子类的无参数构造函数

跨组件共享

  • 如果状态要跨组件共享,则该状态应该由各个组件共同的父元素来管理

通知

  • class NotificationListener extends StatelessWidget
    NotificationListener 可以指定一个模板参数,该模板参数类型必须是继承自Notification

context

  • 我们说过context实际上就是操作Element的一个接口,它与Element树上的节点是对应的,通知会从context对应的Element节点向上冒泡。

动画

  • addListener();它可以用于给Animation添加帧监听器,在每一帧都会被调用。帧监听器中最常见的行为是改变状态后调用setState()来触发UI重建。
animation = new Tween(begin: 0.0, end:300.0).animate(controller);
    animation. addListener((){
      setState(() {
        
      });
    });

等价于

 animation = new Tween(begin: 0.0, end:300.0).animate(controller)
    .. addListener((){//注意这里加了两个点号,以及上一行的分号去掉
      setState(() {
        
      });
    });

多继承

  • class Cow extends Animal with Donwu{//with表示实现多继承,实例化cow的时候,可以用cow对象,调用Animal

注意书写规范

  • 错误的写法即使在没执行的代码里面,只要没有注释掉,就会报错

flutter学习笔记_第2张图片

构造函数

  • 如果父类没有无名无参数的默认构造函数,则子类必须手动调用一个父类构造函数。在:后面构造函数体之前指定要调用的父类构造函数
  • 调用父类构造函数
    默认情况下,子类中的构造函数调用父类的未命名无参数构造函数。 父类的构造函数在子类构造函数体的开头被调用。 如果还使用初始化了列表,则会在调用父类构造函数之前执行。 执行顺序如下:

初始化列表
父类的无参数构造函数
子类的无参数构造函数
如果父类没有未命名的无参数构造函数,则必须手动调用父类中的一个构造函数。 在子类的构造函数体之后用冒号(:)指定父类构造函数

  • 构造函数文章1
  • 构造函数文章2

动画过渡组件

  • 为了表述方便,本书约定,将在Widget属性发生变化时会执行过渡动画的组件统称为”动画过渡组件“
  • 因此,如果也能将AnimationController进行封装,则会大大提高动画组件的易用性。

泛型

  • 泛型的解释

  • 泛型如果为null可以省略不写,为了便于维护和管理,开发中建议加上泛型
  • //使用泛型,则可以省去为每一种类型单独编写代码
    abstract class Cache {
    T getByKey(String key);
    void setByKey(String key, T value);
    }
    表示类里面需要用到数据T,它是一个泛型。代表一个抽象的数据。

  • 限制泛型类型
    class Foo {
    // Implementation goes here…
    String toString() => “Instance of ‘Foo<$T>’”;
    }
    class Extender extends SomeBaseClass {…}
    //使用时可以传入 SomeBaseClass 或者其子类
    var someBaseClassFoo = Foo();
    var extenderFoo = Foo();

//也可以不传入参数,默认为 SomeBaseClass
var foo = Foo();
print(foo); // Instance of ‘Foo’

//传入其他类型的参数则会报错
var foo = Foo();//error


  • 泛型方法
    T first(List ts) {
    // Do some initial work or error checking, then…
    T tmp = ts[0];
    // Do some additional checking or processing…
    return tmp;
    }
    函数的返回值类型 (T).
    参数的类型 (List).
    局部变量的类型 (T tmp).

你可能感兴趣的:(flutter学习笔记)