StatelessWidget是一个不可变的类,充当UI布局中某些部分的蓝图,当某个组件在显示期间不需要改变,或者说没有状态(State),你可以使用它。
StatefulWidget也是不可变的,但是它和一个State对象关联在一起,该对象允许你每次通过调用setState()时,使用新值重建这个widget,当UI可以动态改变时使用StatefulWidget。
WidgetsApp提供了基础的导航能力,和widgets库一起,它包含了很多Flutter使用的基础widget。
MaterialApp和与之相应的的material库,是在WidgetsApp和与之相应的widgets库之上构建的一层,它遵循了Material设计风格,可以再任何平台或者设备上为应用程序提供统一的外观,material库提供了更多的Widget。
在你的项目中,你并不一定要使用MaterialApp,也可以使用CupertinoApp来构建iOS风格的应用程序,这可以使iOS用户感觉更亲切,甚至你也可以自己定义一些widget。
当然可以,你绝对可以嵌套使用Scaffold,这体现Flutter的美,你可以控制整个UI。
Scaffold也是个widget,因此你可以把它放在任何widget可以放置的地方。通过嵌套Scaffold,你可以对抽屉(drawers)、卡片(snack bars)、底页(bottom sheets)进行分层。
packages和plugins可以极大的节约你的时间,当别人已经解决了一个复杂问题时,你没必要再解决一遍,尤其是该解决方案已经获得了很好的评价时。
另一方面,过度依赖三方库也可能有一些风险,他们可能编译不过、有bug或者被丢弃,当你需要切换到新的package或者plugin,可能会对代码做巨大的更改。
这就是为什么需要将业务逻辑和三方库隔离开的原因,你可以通过创建一个Dart的抽象类,来充当package或者plugin的接口。一旦你设置完这种结构后,再遇到需要切换package或者plugin情况,你所要做的就只是重写接口层的具体实现了。
Dart是早期遵循社交距离的采用者,Dart代码运行在一个独立的被称之为isolate的线程上,相互隔离的的isolate不会一起出去玩,最多也就是互相发信息。用计算机术语来说就是,isolate之间不共享内存,它们之间的通信仅通过端口(port)进行。
每一个isolate都有一个event loop,用于管理异步任务的运行,这些任务可能来自于两个队列之中:microtask queue,或者event queue。
Microtasks任务总是优先运行,它们主要是内核任务,开发者不必关心。调用Future时将会把任务放置到event queue中。
很多新手Dart开发者,认为async方法运行在一个单独的线中,尽管对于系统处理的I/O操作这样说可能是正确的,但是它并不适用于你所写的代码,这就是为什么假如你有一个计算量很大的任务,你需要将它运行在一个单独的isolate之中。
当state发生改变时,你将重新构建widget,这种正常且理想的状态,因为它允许用户查看反映在UI中的状态更改。但是重新构建那些不需要改变的UI是性能浪费的。
你可以采取以下措施来减少不必要的Widget重建。
BuildContext实际上是在Element树中的Widget的元素,因此每个Widget都有其自己的BuildContext。
你通常使用BuildContext来获取主题(theme)或者另一个Widget的引用,例如:假如你想要展示一个material dialog,那么你需要获取scaffold的引用,可以通过Scaffold.of(context)来得到它,其中context就是上下文信息,通过of()来往上搜索树,直到找到最近的Scaffold。
阅读didierboelens.com网站的文章Widget — State — Context — Inherited Widget 不仅可以了解到BuildContext,也可以了解到stateful widget的生命周期和inherited widget。
此外,我们的文章Flutter Text Rendering将会带你窥探Flutter底层源码,通过这篇文章,你会了解到build context、elements甚至render对象。
通常你不需要和原生进行交互,因为Flutter或三方插件会处理这些问题,但是,如果你发现确实有特殊需要访问一些底层平台,你可以使用平台channel。
其中一种类型是method channel,数据在Dart侧进行序列化,然后会将数据发送到原生侧,你可以在原生侧编写代码响应交互,然后回传序列化后的数据。在Android侧可以选用Kotlin或者Java,在iOS侧可以使用Objective-C或者Swift进行编写。
但是,在开发web的时候,你不需要使用channel,这时非必要的步骤。
第二种channel类型是event channel,你可以用来从native发送stream数据到flutter侧,这对监控传感器数据的场景很有用。
有多种多样的框架,其中一些比较知名状态管理框架,包括BLOC、伴随ChangeNotifier的Provider、Redux、MobX以及RxDart。这些都适用于中大型的应用程序。如果你只是快速开发一个小demo,那么stateful widget通常就足够了。
与其列出不同状态管理框架的优缺点,不如查看这些框架更适用哪种场景。例如,对于某些人与其淹没在不胜枚举的选择中,不如选择一种比较容易掌握的方案,Provider和MobX都是不错的选择,它们可以直接在state类上调用方法以响应事件,使得这种场景更加直观。
假如你重度依赖流,例如使用Firebase的ApI,那么自然会选择给予数据流的解决方案,比如BLOC和RxDart。
假如你需要撤销/重做功能,那么你需要类似BLOC或者Redux这样,能够很好的处理不可变状态的解决方案。
Material Components widgets
Cupertino (iOS-style) widgets
《深入浅出Dart》Flutter中的Material和Cupertino组件
Flutter 的 Widget,刻意加上 const,真的值得吗?
Flutter系列之Platform Channel使用详解
Flutter 中定义了三种不同类型的 PlatformChannel,主要有三种如下:
Flutter面试题带答案
2023最热门的Flutter和Dart面试问题和答案
22 个 Flutter 开发者必知必会的 Dart 面试题(2020)
「面试精选」Flutter 高频面试题(2023最新版)
https://github.com/ahyangnb/flutter_interview
GSY cookbook
Flutter高级面试题&答案
Flutter 面试题整理