功能和策略
大多数现实世界的应用程序都需要适应不同设备和平台的功能和策略。此页面包含有关如何在代码中处理这些场景的建议。
针对每种设备类型的优势进行设计
#考虑不同设备的独特优势和劣势。除了屏幕尺寸和输入方式,例如触摸、鼠标、键盘,您还能利用哪些其他独特功能?Flutter 允许您的代码在不同的设备上运行,但强大的设计不仅仅是运行代码。思考每个平台最擅长的方面,看看是否有独特的功能可以利用。
例如:苹果的 App Store 和谷歌的 Play Store 有不同的规则,应用程序需要遵守这些规则。不同的主机操作系统在时间和彼此之间也具有不同的功能。
另一个例子是利用网络极低的分享门槛。如果您要部署一个 Web 应用程序,请决定要支持哪些深度链接,并以这些链接为基础设计导航路线。
Flutter 建议的处理基于这些独特功能的不同行为的模式是为您的应用程序创建一组Capability
和 Policy
类。
功能
#功能定义了代码或设备可以做什么。功能的示例包括
- API 的存在
- 操作系统强制执行的限制
- 物理硬件要求(例如摄像头)
策略
#策略定义了代码应该做什么。
策略的示例包括
- 应用商店指南
- 设计偏好
- 引用主机设备的资产或副本
- 服务器端启用的功能
如何构建策略代码
#最简单的机械方法是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;
}
}
将此代码放在一个类中,任何小部件测试都可以模拟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 检查的混合。
通过模拟功能和策略来测试分支代码,这样当功能或策略发生变化时,小部件测试就不需要更改。
在您的功能和策略类中,方法的命名应基于它们试图分支的内容,而不是设备类型。