功能与政策
了解如何使您的应用适应平台、应用商店、公司等所要求的各项能力与策略。
大多数实际应用都需要适应不同设备和平台的能力与策略。本页面提供了在代码中处理这些场景的建议。
根据每种设备类型的优势进行设计
#考虑不同设备的独特优势与劣势。除了屏幕尺寸和输入方式(如触控、鼠标、键盘)之外,您还可以利用哪些其他独特能力?Flutter 使您的代码能够运行在不同的设备上,但优秀的设计不仅仅是让代码跑起来。请思考每个平台最擅长的是什么,并看看是否有可以利用的独特能力。
例如:Apple 的 App Store 和 Google 的 Play Store 有不同的应用准则。不同的宿主操作系统随着时间的推移以及彼此之间,其能力也在不断变化。
另一个例子是利用 Web 极低的共享门槛。如果您要部署一个 Web 应用,请确定要支持哪些深层链接(Deep Links),并据此设计导航路由。
针对这些独特能力处理不同行为时,Flutter 推荐的模式是为您的应用创建一套 Capability(能力)和 Policy(策略)类。
能力
#能力(Capability)定义了代码或设备能够做什么。能力的例子包括:
- API 的存在性
- 操作系统强制的限制
- 物理硬件需求(如摄像头)
策略
#策略(Policy)定义了代码应该做什么。
策略的例子包括:
- 应用商店指南
- 设计偏好
- 引用宿主设备的资源或文案
- 服务器端启用的功能
如何构建策略代码
#最简单的机械式实现方法是使用 Platform.isAndroid、Platform.isIOS 和 kIsWeb。这些 API 可以机械地让您知道代码正在何处运行,但随着应用可运行范围的扩大以及宿主平台功能更新,这种方式会带来一些问题。
以下指南阐述了在为应用开发能力和策略时的最佳实践:
避免使用 Platform.isAndroid 及类似函数来进行布局决策或对设备能力做出假设。
相反,应在方法中描述您想要分支处理的逻辑。
示例:您的应用在网站中有一个购买链接,但出于策略原因,您不希望在 iOS 设备上显示该链接。
bool shouldAllowPurchaseClick() {
// Banned by Apple App Store guidelines.
return !Platform.isIOS;
}
...
TextSpan(
text: 'Buy in browser',
style: new TextStyle(color: Colors.blue),
recognizer: shouldAllowPurchaseClick ? TapGestureRecognizer()
..onTap = () { launch('<some url>') : null;
} : null,
通过增加一层间接性,您得到了什么?代码更加清晰地说明了为什么存在该分支路径。此方法可以直接存在于类中,但很可能代码的其他部分也需要进行相同的检查。如果是这样,请将该代码放入一个专门的类中。
class Policy {
bool shouldAllowPurchaseClick() {
// Banned by Apple App Store guidelines.
return !Platform.isIOS;
}
}
将此代码放在类中后,任何 Widget 测试都可以 Mock Policy().shouldAllowPurchaseClick,从而独立于设备运行环境验证行为。这也意味着以后如果您决定在 Web 上进行购买不适合 Android 用户,您可以更改实现逻辑,而无需更改可点击文本的测试代码。
能力
#有时您希望代码执行某项操作,但 API 不存在,或者您依赖的插件功能尚未在您支持的所有平台上实现。这是设备能够做什么的一种局限。
这些情况类似于上述的策略决策,但它们被称为能力。为什么在类结构相似的情况下要将策略类与能力类分开?Flutter 团队在生产级应用中发现,对应用能做什么和应该做什么进行逻辑区分,有助于大型产品在代码编写完成后,更好地应对平台能力的变化或新的需求,以及您自身偏好的调整。
例如,考虑某个平台增加了一项新权限,要求用户在您的代码调用敏感 API 之前必须与系统对话框进行交互的情况。您的团队针对平台 1 完成了这项工作,并创建了一个名为 requirePermissionDialogFlow 的能力类。后来,如果平台 2 也增加了类似要求(但仅针对新 API 版本),那么 requirePermissionDialogFlow 的实现现在就可以检查 API 级别并为平台 2 返回 true。您复用了之前的工作成果。
策略
#我们建议最初从一个 Policy 类开始,即使看起来您似乎不会做出很多基于策略的决策。随着类复杂度的增加或输入项的扩展,您可以决定按功能或其他标准拆分策略类。
对于策略实现,您可以使用编译时、运行时或远程过程调用 (RPC) 支持的实现方式。
编译时策略检查适用于偏好不太可能改变且意外更改值可能产生巨大影响的平台。例如,如果某个平台要求您不得链接到 Play 商店,或者要求您根据应用内容使用特定的支付提供商。
运行时检查适用于确定用户是否可以使用触摸屏。Android 有一个可以检查的特性,您的 Web 实现则可以检查最大触控点数。
基于 RPC 的策略更改适用于增量功能发布或未来可能会发生变化的决策。
概述
#使用 Capability 类来定义代码能够做什么。您可以检查 API 的存在性、操作系统强制限制以及物理硬件要求(如摄像头)。能力通常涉及编译时或运行时检查。
使用 Policy 类(或根据复杂度使用多个类)来定义代码应该做什么,以符合应用商店指南、设计偏好,以及需要引用宿主设备的资源或文案。策略可以是编译时、运行时或 RPC 检查的组合。
通过 Mock 能力和策略来测试分支代码,这样当能力或策略发生变化时,Widget 测试无需更改。
在命名能力和策略类的方法时,应基于它们试图进行分支处理的逻辑含义,而不是基于设备类型。