Flutter for UIKit developers(《给 UIKit 开发者的 Flutter 指南》) 笔记及翻译

最近,我通过 Flutter 官网以及一些 flutter 书籍、视频学习 Flutter。官方文档有一篇名为 Flutter for UIKit developers 的文档,名字翻译为《给 UIKit 开发者的 Flutter 指南》。全文用一种 UIKit 开发视角来大致描述了 Flutter 的特性,包含了最常见开发流程中,最基础的 Flutter 使用案例。

完整读完的过程中,写了示例代码并配合真机调试,让我对 Flutter 开发过程有了一个大致的了解,有一种迷雾中看见了光的感觉。断断续续小两周的时间,感觉已经可以算是上手了。

阅读过程中,我做了一些笔记,虽然文档是全英文的,还算易理解。笔记内容我做了粗糙的翻译,当作是提升下阅读能力的练习。

1. Flutter is a framework for building cross-platform application that uses the Dart programming language.

Flutter 是一个使用 Dart 语言构建跨平台应用的框架。

2. In Flutter,the rough equivalent to a UIView is a widget. Widget don’t map exactly to iOS views. There are Dart type of Widget: StatelessWidget and StatefulWidget.

在 Flutter 中,Widget 基本相当于一个 UIView。但是,Widget 和 iOS Views 的作用不完全一样。Widget 分为两种类型:无状态组件和有状态组件。

3. A common StatelessWidget is the Text widget. If you look at implementation of the Text widget, you’ll find it subclasses StatelessWidget.

Text Widget 是一个常见的无状态族组件(StetelessWudget),如果你查看 Text widget 的实现,你会发现它是 StatelessWidget 的子类。

4. Widget layout: You can add padding to any widget, which mimics the functionality of constraints in iOS.

组件布局:你可以给任何组件添加 padding,这模仿了 iOS 中约束的功能。

5. Animations: In Flutter, use the animation library to warp widgets inside an animated widget.

动画:在 Flutter 中,使用 animation 库将一些组件(widgets)封装到一个动画组件里。

6. Use an AnimationController, which is an Animation that can pause, seek, stop, and reverse the animation. It requires a Ticker that signals when vsync happens and produces a linear interpolation between 0 and 1 on each frame while it’s running. You then create one or more Animations and attach them to the controller.

使用 AnimationController 可以对动画进行暂停、查找、停止和反转操作。AnimationController 继承自 Animation 。AnimationController 必需一个 Ticker,当垂直同步时发出信号,运行时在每一帧产生0-1的线性插值。可以创建一个或多个 Animation 并把它们添加到当前的 controller。

7. Drawing on the screen: In UIKit, you use CoreGraphics to draw lines and shapes to the screen. Flutter has a different API based on the Canvas class, with two other classes that help you to draw: CustomPaint and CustomPainter, the latter of which implements your algorithm to draw to the canvas.

在屏幕上绘制:在 UIKit 中,你可以使用 CoreGraphics 在屏幕上绘制线段和图形。Flutter 有一个基于 Canvas 类的绘制 API,API 有两个类用来绘制图形:CustomPaint 和 CustomPainter。CustomPainter 类可以根据你编写的图形算法代码,在画布上绘制你想要的图形。

8. Widget opacity: In UIKit, everything has .opacity or .alpha. In Flutter, most of the time you need to wap a widget in an Opacity widget to accomplish this.

组件不透明度:在UIKit 中,所有类都有 .opacity 或是 .alpha 属性来设置 view 的不透明度。但是在 Flutter 中,大多数时候,需要通过把一个 widget 包装在一个 Opacity widget 里面来实现不透明度的设置。

9. Custom Widgets: In UIKit, you typically subclass UIView, or use a pre-existing view, to override and implement methods that achieve the desired behavior. In Flutter, build a custom widget by composing smaller widgets (instead of extending them).
自定义组件:在 UIKit 中,你通常通过继承 UIView ,或是使用一个已存在的 view,通过重写和实现期望方法来自定义组件。在 Flutter 中,构建一个自定义 widget 是通过组合更小功能粒度的组件(而不是扩展它们)来实现的。

**10. Navigation: In UIKit, to travel between view controllers, you can use a UINavigationController that manages the stack of view controllers to display. **

在 UIKit 中,想要切换视图控制器,你可以通过使用 UINavigationController 来管理需要显示的视图控制器堆栈。

11. Flutter has a similar implementation, using a Navigator and Routes. A Route is an abstraction for a “screen” or “page” of an app, and a Navigator is a widget that manages routes. A route roughly maps to a UIViewController. The navigator works in a similar way to the iOS UINavigationController, in that it can push() and pop() routes depending on whether you want navigate to, or back from, a view.

Flutter 有类似的实现,使用 Navigator 和 Routes。一个路由(Route)是一个 App 的一个“屏幕”或是“页面”的抽象表示,一个导航(Navigator)是一个管理路由的组件。一个路由大致对应一个 UIViewController。导航(Navigator)工作方式和 iOS UINavigationController 一样,可以通过 push() 和 pop() 来控制页面的前进或后退到一个页面。

12. To navigate between pages, you have a couple options:
- Specify a Map of route names.
- Directly navigate to a route.

要实现页面的导航,需要做一组操作:

  • 指定一个路由和路由名字的映射。
  • 直接使用路由名字进行导航。

13. Navigating to another app: In UIKit, to send the user to another application, you use a specific URL scheme. For the system level apps, the scheme depends on the app. To implement this functionality in Flutter, create a native platform integration, or use an existing plugin, such as url_launcher.

跳转到第三方 app:在 UIKit 中,为了让用户跳转到第三方应用,必须使用特定的 URL scheme。对于系统应用来说,不同的系统应用有对应的 scheme。为了在 Flutter 里实现这个功能,可以集成原生平台代码,或是使用一个已有的第三方插件,比如 url_launcher。

14. Handling localization: Unlike iOS, which has the localizable.strings file, Flutter doesn’t currently have a dedicated system for handling strings. At the moment, the best practice is to declare your copy text in a class as static fields and access them form there.

本地化:和使用 localizable.strings 文件完成本地化处理的 iOS 不同,Flutter 目前还没有用来处理字符串本地化的专用系统。现在,最好的处理方法是,在一个类中,声明本地化文本为静态字段,然后使用这些静态字段。

15. Managing deoendencies: Flutter uses Dart’s build system and the Pub package manager to handle dependencies. The tools delegate the building of the native Android and iOS wapper apps to the respective build systems.
While there is a Podfile in the iOS folder in your Flutter project, only use this if you are adding native dependencies needed for per-platform integration.
In general, use pubspec.yaml to declare external dependencies in Flutter. A good place to find great packages for Flutter is on pub.dev.

依赖管理:Flutter使用 Dart 的构建系统和 Pub 包管理器来处理依赖关系。这些工具委托原生 Android 和 iOS 各自的构建系统来处理构建工作。
虽然在你的 Flutter 项目中的 iOS 文件夹里也存在一个 Podfile 文件,但是只有当原生平台集成需要添加原生依赖时才会使用到。
通常,Flutter 使用 pubspec.yaml 来声明外部依赖。你可以在 pub.dev 上找到很棒的 Flutter 库

16. ViewControllers: In UIKit, a ViewController represents a portion of user interface, most commonly used for a screen or section. These are composed together to build complex user interface, and help scale your application’s UI.
In Flutter, this job falls to Widgets. As mentioned in the Navigation section, screens in Flutter are represented by Widgets since “everything is a widget!” Use a navigator to move between different Routes that represent different screens or pages.

视图控制器:在 UIKit 中,一个 ViewController 是用户界面的组成部分,最常用作一个界面或是局部界面。多个 ViewController 组合起来构建复杂的用户界面并扩展你应用的 UI。
在 Flutter 中,这项工作由 Widget 负责。就像导航里提到的一样,界面由 Widget 表示,因为“一切都是 Widget!”。通过导航(Navigator)切换不同的路由(Route)实现展示不同的界面。

17. Lifecycle events: In UIKit, you can override methods to the ViewController to capture lifecycle methods for view itself, or register lifecycle callbacks in the AppDelegate. In Flutter, you have neither concept, but you can instead listen to lifecycle events by hooking into the WidgetsBinding observer and listening to the didChangeAppLifecycleState() change event. The observable lifecycle events are:

- inactive: The application is in an inactive state and is not receiving user input. This event only works on iOS, as there is no eqivalent event on Andriod.

- paused: The application is not currently visible to the user, isnot respondinng to user input, but is runninng in the background.

- resumed: The application is visible and responding to user input.

- suspending: the application is suspended momentarily. The iOS platform has no equivalent event.

生命周期事件:在 UIKit中,你可以重写 ViewController 自身的生命周期方法来获取生命周期事件,或是在 AppDelegate 中注册生命周期回调。在 Flutter 中,没有这两个概念,但是你通过 Hooking WidgetsBinding 观察者并监听 didChangeAppLifecycleState() 事件的变化。可观察的生命周期事件如下:

  • 不活跃:应用处于一个不活跃的状态并且不能接受用户输入。这个事件只在 iOS 上有效,Android 上没有对应的事件。
  • 暂停:应用当前对用户不可见,不能响应用户输入,但是在后台处于运行中。
  • 恢复:应用对用户可见并且可以响应用户输入。
  • 挂起:应用暂时挂起。iOS 平台没有相应的事件。

18. In Flutter, ListView has a similar implementation with UITableView. Due to Flutter’s immutable widget pattern, you pass a list of widgets to your Listview, and Flutter takes care of making sure that scrolling is fast and smooth.
- In Flutter, use touch handling provided by the passed-in widgets.
- In Flutter, if you update the list of widgets inside a setState(), you quickly see that your data doesn’t change visually. This is because when setState() is called, the Flutter rendering engine looks at the widget tree to see if anything has changed. When it get your ListView, it performs an == check, and determines that the two ListView are the same. Nothing has changed, so no update is required.
- For small data sets, a simple way to update your ListView, create a new List inside of setState(), and copy the date from the old list to the new list.
- The recommend, efficient, and effective way to build a list use a ListView.Builder. This method is great when you have a dynamic list or a list with very large amounts of data.
- Instead of creating a ListView, create a ListView.builder that takes two key parrameters: the initial length of the list, and an ItemBuilder funtion.
- In Flutter the ListView allows a user to scroll your content if needed. ListView widget acts as both a ScrollView and an iOS TableView, as you can layout widgets in a vertical format.

在 Flutter 中,ListView 和 UITableView 有类似的实现。因为 Flutter 的不可变小组件模式,你只需向你的 ListView 传递一个需要展示的组件数组,Flutter 会确保 ListView 的滚动迅速、丝滑。

  • 在 Flutter 中,触摸事件是通过传入的组件处理的。
  • 在 Flutter 中,如果你通过 setState() 方法更新了组件数组,你会很快发现你的更新数据并没有让 UI 发生变化。这是因为当 setState() 方法被调用时,Flutter 的渲染引擎检查了组件树是否有变化。当检查到你的 ListView 时,它会执行一个 == 判断,然后得出新旧两个 ListView 是相同的。没有任何变化,所以没有 UI 的更新。
  • 对于小规模数据,有一个简单的方法来更新你的 ListView,在 setState() 方法中创建一个新的数组,并把数据从旧数组中复制到新数组。
  • 使用 ListView.Builder 来构建数据,是一个推荐的、高效的并且有效的方法。这个方法在你需要处理动态数组或是大规模数据时非常地好用。
  • 创建一个 List.Builder 需要注意两个关键参数:列表的初始长度,和一个 ItemBuilder 方法。
  • 在 Flutter 中,ListView 在需要时可以满足用户的滚动操作。ListView 小组件表现得像一个 ScrollView 和 一个 iOS UITableView,你可以在垂直方向布局需要的组件。

19. Gesture detection and touch event handling:
- there are two ways of adding touch listeners:
If the widget supports event detection, pass a function to it, and handle the event in the function.
If the widget doesn’t support event detection, wrap the widget in a GestureDetector and pass a function to the onTap paremeter.
- Using GestureDetector we can listen to a wide range of gestures such as: Tapping, Double tapping, Long pressing, Vertical dragging, Horizontal dragging.

手势监听和触摸事件处理:

  • 添加触摸监听有两种方式:
    如果组件支持事件监听,传递一个处理事件的方法给组件。
    如果组件不支持事件监听,把组件包装到一个 GestureDetector 中,然后传递一个处理事件的方法给 onTap 参数。
  • 使用 GestureDetector 我们可以监听各种手势,比如:点击、双击、长按、垂直拖拽、水平拖拽。

20. Themes, Style, and media: Flutter application are easy to style.

- You can take full advantage of Material Components in your app, declare a top-level widget, MaterialApp, as the entry point to your application. MaterialApp is a convenience widget that wraps a number of widgets that are commonly required for applications implementing Material Design. It builds upon a WidgetsApp by adding Material specific functionality.

- Using custom fonts: Place the font file in a folder and reference it in the pubspec.yaml file, similar to how you import images.

- Styling text: The style parameter of a Text widget takes a TextStyle Object, where you can customize many parameters for text style.

- Bundling images in apps:
Flutter apps have only assets. As with iOS,assets are any type of file, not just images.
For image, Flutter follows a simple density-based format like iOS. Image assets might be 1.0x, 2.0x, 3.0x, or any other multiplier. The so called devicePixelRatio expresses the ratio of physical pixels in a single logical pixel.
You can decleare the assets (with location) in the pubspec.yaml file, and Flutter picks them up.
You can now access your images using AssetImage, Or directly in an Image widget.

- Retrieving user input: If you have a TextField or a TextFormField, you can supply a TextEditingController to retrieve user input.

- InputDecoration object can easily show a “hint” or a placeholder text for your field. If you don’t want to start off by showing an error. Instead, when the user has entered invalid data, update the state, and pass a new InputDecoration object.
主题、样式和媒体:Flutter 应用很容易设计样式风格。

  • 你可以在你的应用中充分使用原始组件(Material Components),定义一个顶级组件——MaterialApp,作为你应用的入口。MaterialApp 是一个很便捷的组件,它封装了实现 Material Design 的一些常用组件。通添加一些特定 Material 功能构建 MaterialApp。

  • 使用自定义字体:将字体文件放置到一个文件夹中,然后在 pubspec.yaml 文件中添加引用,和引入图片类似。

  • 改变文本样式:文本组件的 style 参数需要一个 TextStyle 对象,它可以自定义很多的参数来改变文本样式。

  • 图片打包管理:
    Flutter 应用只有资源。和 iOS 一样,资源可以是任何类型的文件,不仅仅是图片。
    对于图片,Flutter 和 iOS 一样,遵循一个简单的基于密度的格式。图片资源可能是 1.0x,2.0x,3.0x,或者任何倍数。devicePixelRatio 表示单个逻辑像素中包含多少个物理像素的比例。
    你可以在 pubspec.yaml 文件中声明资源(可以指定位置),Flutter 会负责收集整理。
    完成上述操作后,你可以通过 AssetsImage 访问你的图片资源,或是直接使用 Image widget。

  • 检索用户输入:如果你有一个 TextField 或是 TextFormField,你可以使用一个 TextEditingController 来检索用户输入。

  • 使用输入组件装饰对象(InputDecoration object)很容易在你的输入框实现展示一个“提示”或是“占位文本”。如果不想一开始就显示一个错误信息。那就,在用户输入了无效数据时,再更新状态,赋值一个新的 InputDecoration 对象。

21. Threading:Dart has a single-threaded execution model, with support for Isolates(a way to run Dart code on another thread), an event loop, and asynchronous progframming.
Unless you spawn an Isolate, your Dart code runs in the main UI thread and is driven by an event loop. Flutter’s event loop is equivalent to iOS main loop-that is, the Looper that is attachedd to the main thread.

多线程:Dart 是一个单线程执行模式,支持隔离(一种在另一个线程上运行 Dart 代码的方法)、事件循环和异步编程。
除非你生成一个隔离,你的 Dart 代码会在主 UI 线程中执行并由事件循环驱动。Flutter 的事件循环相当于 iOS 的主循环,就是说,循环程序(Looper)是附加到主线程的。

Dart language provides async/await, to perfom asynchronous work.
Dart 语言提供 async/await 来执行异步操作。

22. In Flutter, user Isolate to take advantage of multiple CPU cores to do long-running or computationally intensive tasks. Isolate are separete execution threads that do not share any memory with the main execution memory heap. Isolates are true to their name, and cannot shre memory.

在 Flutter 中,用户隔离可以充分利用多核处理器来执行需要长时间的或是需要大量计算的任务。隔离是单独的执行线程,不会和主线程共享任何内存。隔离名副其实,不共享内存。

23. Network requests: To use the http package, add it to your dependencies in pubspec.yaml. To make a network call, call await on the async function http.get().

网络请求:为了使用 http 库,在 pubspec.yaml 中把它添加到你的依赖里。对异步方法 http.get() 调用 await,来实现一次网络请求。

24. Progress: Use a ProgressIndicator widget. Show the progress praogrammatically by controlling when it’s rendered through a boolean flag.

进度:使用一个 ProgressIndicator 组件。可以编写一个布尔标志来控制进度的显示时机。

感兴趣,可以查看 Flutter for UIKit developers 原文。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值