本文档适用那些希望将现有 iOS 经验应用于 Flutter 的开发者。如果你拥有 iOS 开发基础,那么你可以使用这篇文档开始学习 Flutter 的开发。
开发 Flutter 时,你的 iOS 经验和技能将会大有裨益,因为 Flutter 依赖于移动操作系统的众多功能和配置。Flutter 是用于为移动设备构建用户界面的全新方式,但它也有一个插件系统用于和 iOS(及 Android)进行非 UI 任务的通信。如果你是 iOS 开发专家,则你不必将 Flutter 彻底重新学习一遍。
你可以将此文档作为 cookbook,通过跳转并查找与你的需求最相关的问题。
在 iOS 中,构建 UI 的过程中将大量使用 view 对象。这些对象都是 UIView 的实例。它们可以用作容器来承载其他的 UIView,最终构成你的界面布局。
在 Flutter 中,你可以粗略地认为 Widget 相当于 UIView 。Widget 和 iOS 中的控件并不完全等价,但当你试图去理解 Flutter 是如何工作的时候,你可以认为它们是“声明和构建 UI 的方法”。
然而,Widget 和 UIView 还是有些区别的。首先,widgets 拥有不同的生存时间:它们一直存在且保持不变,直到当它们需要被改变。当 widgets 和它们的状态被改变时,Flutter 会构建一颗新的 widgets 树。作为对比,iOS 中的 views 在改变时并不会被重新创建。但是与其说 views 是可变的实例,不如说它们被绘制了一次,并且直到使用 setNeedsDisplay() 之后才会被重新绘制。
此外,不像 UIView,由于不可变性,Flutter 的 widgets 非常轻量。这是因为它们本身并不是什么控件,也不会被直接绘制出什么,而只是 UI 的描述。
Flutter 包含了 Material 组件库。这些 widgets 遵循了 Material 设计规范。MD 是一个灵活的设计系统,并且为包括 iOS 在内的所有系统进行了优化。
但是用 Flutter 实现任何的设计语言都非常的灵活和富有表现力。在 iOS 平台,你可以使用 Cupertino widgets 来构建遵循了 Apple’s iOS design language 的界面。
在 iOS 上更新 views,只需要直接改变它们就可以了。在 Flutter 中,widgets 是不可变的,而且不能被直接更新。你需要去操纵 widget 的 state。
这也正是有状态的和无状态的 widget 这一概念的来源。一个 StatelessWidget 正如它听起来一样,是一个没有附加状态的 widget。
StatelessWidget 在你构建初始化后不再进行改变的界面时非常有用。
举个例子,你可能会用一个 UIImageView 来展示你的 logo image 。如果这个 logo 在运行时不会改变,那么你就可以在 Flutter 中使用 StatelessWidget 。
如果你希望在发起 HTTP 请求时,依托接收到的数据动态的改变 UI,请使用 StatefulWidget。当 HTTP 请求结束后,通知 Flutter 框架 widget 的 State 更新了,好让系统来更新 UI。
有状态和无状态的 widget 之间一个非常重要的区别是,StatefulWidget 拥有一个 State 对象来存储它的状态数据,并在 widget 树重建时携带着它,因此状态不会丢失。
如果你有疑惑,请记住以下规则:如果一个 widget 在它的 build 方法之外改变(例如,在运行时由于用户的操作而改变),它就是有状态的。如果一个 widget 在一次 build 之后永远不变,那它就是无状态的。但是,即便一个 widget 是有状态的,包含它的父亲 widget 也可以是无状态的,只要父 widget 本身不响应这些变化。
下面的例子展示了如何使用一个 StatelessWidget 。一个常见的 StatelessWidget 是 Textwidget。如果你查看 Text 的实现,你会发现它是 StatelessWidget 的子类。
Text( 'I like Flutter!', style: TextStyle(fontWeight: FontWeight.bold), );阅读上面的代码,你可能会注意到 Text widget 并不显示地携带任何状态。它通过传入给它的构造器的数据来渲染,除此之外再无其他。
但是,如果你希望 I like Flutter 在点击 FloatingActionButton 时动态的改变呢?
为了实现这个,用 StatefulWidget 包裹 Text widget,并在用户点击按钮时更新它。
举个例子:
class SampleApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Sample App', theme: ThemeData( primarySwatch: Colors.blue, ), home: SampleAppPage(), ); } } class SampleAppPage extends StatefulWidget { SampleAppPage({Key key}) : super(key: key); @override _SampleAppPageState createState() => _SampleAppPageState(); } class _SampleAppPageState extends State<SampleAppPage> { // Default placeholder text String textToShow = "I Like Flutter"; void _updateText() { setState(() { // update the text textToShow = "Flutter is Awesome!"; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Sample App"