Flutter特性管理插件featurehub_client_sdk的使用

发布于 1周前 作者 wuwangju 来自 Flutter

Flutter特性管理插件featurehub_client_sdk的使用

Dart SDK 实现了用于FeatureHub.io - 开源特性标志管理、A/B测试和远程配置平台。适用于Flutter Web、移动和桌面。

它提供了Feature仓库的核心功能,该仓库保存特性及其状态,并创建事件(例如发送特征更新)。此库依赖于我们自己的EventSourcing库的Dart版本。

获取详细文档

可以在这里查看FeatureHub的详细文档。

访问演示FeatureHub管理控制台

可以在这里访问演示FeatureHub管理控制台。

入门指南

添加依赖

pubspec.yaml文件中添加以下依赖:

dependencies:
  featurehub_client_sdk: ^1.3.0 # 最新版本

导入包

在需要使用特性的文件中导入包:

import 'package:featurehub_client_sdk/featurehub.dart';

连接到FeatureHub

1. 获取API密钥

找到并复制你的服务器评估API密钥(从FeatureHub管理控制台的API密钥页面获取)。这将用于配置环境中的特性更新。它应该类似于以下格式:

default/806d0fe8-2842-4d17-9e1f-1c33eedc5f31/tnZHPUIKV9GPM4u0koKPk1yZ3aqZgKNI7b6CT76q

注意:此SDK仅接受服务器评估的API密钥,适用于不安全的客户端,如浏览器或移动设备。这意味着你每次只能评估一个用户。更多详情可以在这里查看。

2. 连接到FeatureHub服务器

通过提供FeatureHub服务器URL和上一步中的API密钥来创建FeatureHub仓库,该仓库保存特性状态:

repository = ClientFeatureRepository();

fhConfig = FeatureHubConfig(
  'http://localhost:8064/pistachio',
  [
    '135f4735-f1ab-4061-b69c-3a3debf2e344/CFArRq8UfTHcaK1fkOAtnKnbrFG0xQMcZuFPfUBh'
  ],
  repository!,
  timeout: 2
);

3. 从代码中获取特性状态

class Sample extends StatelessWidget {
  const Sample({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('我的应用'),
      ),
      body: StreamBuilder<FeatureStateHolder>(
        stream: repository!.feature('CONTAINER_COLOUR_FEATURE').featureUpdateStream,
        builder: (context, snapshot) {
          if (!snapshot.hasData) return SizedBox.shrink();
          return Container(
            color: snapshot.data?.stringValue == 'blue' ? Colors.blue : Colors.green,
            child: Text('Hello world!'),
          );
        },
      ),
    );
  }
}

4. 请求最新特性状态

请求方法是一个异步方法,它会直接将内容返回到仓库。如果请求失败,则捕获失败并将失败状态发送到仓库,这将在就绪监听器中更新错误状态(例如FAILED)。

fhConfig!.request();

如果请求没有数据或API密钥不存在,则不会被视为错误,因为它们可能只是尚未可用,并且你不希望应用程序失败。

Flutter示例应用

有一个完整的示例,你可以跟随它来演示如何在Flutter应用中处理具有字符串类型键“CONTAINER_COLOUR”的特性。容器颜色将根据特性值更新状态,该特性值可以是“黄色”、“绿色”、“紫色”等。(参见上面的视频剪辑)

特性状态方法

以下是获取原始特性值的方法:

  • getFlag('FEATURE_KEY') 返回布尔特性的值,如果没有找到则返回null
  • getNumber('FEATURE_KEY') | getString('FEATURE_KEY') | getJson('FEATURE_KEY') 返回特性值或空值或不存在时返回null
  • exists('FEATURE_KEY') 如果特性键存在则返回true,否则返回false
  • feature('FEATURE_KEY') | getFeatureState('FEATURE_KEY') 返回FeatureStateHolder如果特性键存在,否则返回null

使用高级功能(滚动策略)

FeatureHub支持对特定环境下的单个特性值进行复杂的滚动策略的服务器端评估。这包括预设规则,例如按用户键、国家、设备类型、平台类型,以及百分比拆分规则和自定义规则。

编码滚动策略

我们可以跟踪几个预设策略规则:用户键、国家、设备和平台。然而,如果这些规则不能满足您的需求,您还可以附加自定义规则。自定义规则可以创建为以下类型:字符串、数字、布尔值、日期、日期时间、语义版本、IP地址。

FeatureHub SDK将根据这些规则匹配您的用户,因此您需要在SDK中提供要匹配的属性:

发送预设属性

为了支持用户键规则,提供以下属性:

repository.clientContext.userKey('ideally-unique-id').build();

为了支持国家规则:

repository.clientContext.country(StrategyAttributeCountryName.NewZealand).build();

为了支持设备规则:

repository.clientContext.device(StrategyAttributeDeviceName.Browser).build();

为了支持平台规则:

repository.clientContext.platform(StrategyAttributePlatformName.Android).build();

为了支持语义版本规则:

repository.clientContext.version('1.2.0').build();

如果要组合多个属性,可以这样做:

repository.clientContext
  .userKey('ideally-unique-id')
  .country(StrategyAttributeCountryName.NewZealand)
  .device(StrategyAttributeDeviceName.Browser)
  .platform(StrategyAttributePlatformName.Android)
  .version('1.2.0')
  .build();

发送自定义属性

为了添加自定义键/值对,使用attr(key, value)

repository.clientContext.attr('first-language', 'russian').build();

或者使用数组值(仅适用于自定义规则):

repository.clientContext.attrs('languages', ['russian', 'english', 'german']).build();

您也可以使用repository.clientContext.clear()来清空上下文。

在所有情况下,您需要调用build(),然后调用featurehubApi!.request()以重新触发将新属性传递给服务器进行重新计算。

百分比拆分

对于百分比分割,您只需要提供用户键或会话键:

repository.clientContext.userKey('ideally-unique-id').build();

或者

repository.clientContext.sessionKey('session-id').build();

有关百分比分割和特性实验的更多信息,请参阅这里

通过SSE(服务器发送事件)更新特性

在上面的例子中,从FeatureHub服务器检索特性状态的机制基于GET请求。但是,还有一个选项是使用SSE协议更新FeatureHub仓库。SSE方法的优点是可以实时更新特性,因为它保持与FeatureHub边缘服务器的连接。然而,正如您想象的那样,这对于电池来说是一个昂贵的操作,我们不建议在移动设备上长时间使用。请仔细考虑是否决定使用这种方法。

由于这两种更新方法是可互换的,您可以在同一应用程序中包含它们。如果您在应用程序切换到后台时使用GET,在切换到前台时使用EventSource,如果即时更新很重要,您可以在这两者之间切换。

错误处理

如果由于某种原因连接到FeatureHub服务器失败——无论是初始连接还是过程中的某个原因,您将收到一个就绪事件以指示现在已失败。

enum Readyness {
  NotReady = 'NotReady',
  Ready = 'Ready',
  Failed = 'Failed'
}

FeatureHub测试API

FeatureHub测试API在此SDK中可用,但并未单独提取为类。测试API的目的允许您在编写自动化集成测试时主要更新特性。

我们提供了一种使用FeatureServiceApi.setFeatureState方法实现此目的的方法。使用API基于您的API密钥的权利。通常,您应该只在测试环境中给予服务帐户写权限。

当指定密钥时,边缘服务将获取特性的最新值,并将其与您的更改进行比较,然后根据您的权限采取相应措施。

您需要传递一个FeatureStateUpdate实例,它接受三个可选值:

  • lock - 布尔类型。如果为true则尝试锁定,false则尝试解锁。无值将不会进行任何更改。
  • value - 动态类型的值,当您希望设置一个值时传递。如果不希望取消设置值则不要传递。对于标志而言,这意味着设置为false(如果为空),但对于其他情况,则使其为空(不传递)。
  • updateValue - 设置此值为true,如果希望使值字段为空。否则,无法区分未设置值和设置为null的情况。

我们不提供包装类,因为大多数代码直接来自featurehub_client_api,并且您需要在项目中包含该库及其依赖项才能使用此功能。

示例代码可能如下所示:

final _api = FeatureServiceApiDelegate(ApiClient(basePath: hostURL));
_api.setFeatureState(apiKey, featureKey, FeatureStateUpdate()..lock = false ..value = 'TEST');

更多关于Flutter特性管理插件featurehub_client_sdk的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter特性管理插件featurehub_client_sdk的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用featurehub_client_sdk插件进行特性管理的代码示例。这个示例将展示如何初始化FeatureHub客户端,获取特性值,并监听特性的变化。

首先,确保你已经在pubspec.yaml文件中添加了featurehub_client_sdk依赖:

dependencies:
  flutter:
    sdk: flutter
  featurehub_client_sdk: ^最新版本号 # 替换为实际的最新版本号

然后,运行flutter pub get来安装依赖。

接下来,你可以按照以下步骤在你的Flutter应用中使用featurehub_client_sdk

  1. 初始化FeatureHub客户端
import 'package:featurehub_client_sdk/featurehub_client_sdk.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late FeatureHubClient _featureHubClient;

  @override
  void initState() {
    super.initState();

    // 配置FeatureHub客户端
    final FeatureHubClientConfig config = FeatureHubClientConfig(
      apiKey: '你的API密钥', // 替换为你的FeatureHub API密钥
      url: 'https://你的FeatureHub服务器URL/edge', // 替换为你的FeatureHub服务器URL
    );

    // 创建FeatureHub客户端实例
    _featureHubClient = FeatureHubClient(config: config);

    // 初始化客户端并获取特性值
    _featureHubClient.init().then((_) {
      // 获取特性值示例
      bool? myFeatureFlag = _featureHubClient.featureValue<bool>('my-feature-flag-key');
      print('My Feature Flag Value: $myFeatureFlag');

      // 监听特性变化
      _featureHubClient.onFeatureValueChanged<bool>('my-feature-flag-key').listen((newValue) {
        print('My Feature Flag Value Changed: $newValue');
        setState(() {
          // 根据特性值更新UI
        });
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('FeatureHub Demo'),
        ),
        body: Center(
          child: Text('Check the console for feature flag values and changes.'),
        ),
      ),
    );
  }

  @override
  void dispose() {
    // 释放资源
    _featureHubClient.dispose();
    super.dispose();
  }
}
  1. 在UI中使用特性值

上面的代码示例中,我们仅在控制台中打印了特性值。在实际应用中,你可能需要根据特性值来更新UI。例如,如果特性值控制某个按钮的显示,你可以这样做:

class _MyAppState extends State<MyApp> {
  late FeatureHubClient _featureHubClient;
  bool? _myFeatureFlagValue;

  @override
  void initState() {
    super.initState();

    final FeatureHubClientConfig config = FeatureHubClientConfig(
      apiKey: '你的API密钥',
      url: 'https://你的FeatureHub服务器URL/edge',
    );

    _featureHubClient = FeatureHubClient(config: config);

    _featureHubClient.init().then((_) {
      _myFeatureFlagValue = _featureHubClient.featureValue<bool>('my-feature-flag-key');

      _featureHubClient.onFeatureValueChanged<bool>('my-feature-flag-key').listen((newValue) {
        setState(() {
          _myFeatureFlagValue = newValue;
        });
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('FeatureHub Demo'),
        ),
        body: Center(
          child: _myFeatureFlagValue == true
              ? ElevatedButton(
                  onPressed: () {
                    // 按钮点击事件
                  },
                  child: Text('Feature Enabled Button'),
                )
              : Text('Feature is disabled'),
        ),
      ),
    );
  }

  @override
  void dispose() {
    _featureHubClient.dispose();
    super.dispose();
  }
}

在这个示例中,我们根据_myFeatureFlagValue的值来决定是否显示一个按钮。当特性值变化时,我们会通过setState方法更新UI。

请注意,你需要将你的API密钥你的FeatureHub服务器URL替换为实际的FeatureHub配置信息。

这个示例展示了如何在Flutter项目中使用featurehub_client_sdk进行特性管理,包括初始化客户端、获取特性值和监听特性变化。根据你的实际需求,你可以进一步扩展这个示例。

回到顶部