Flutter特性管理插件launchdarkly_flutter_client_sdk的使用

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

Flutter特性管理插件launchdarkly_flutter_client_sdk的使用

LaunchDarkly Client-side SDK for Flutter

Action Status Pub

LaunchDarkly 是一个功能管理平台,每天提供数万亿个功能标记,帮助团队更快地构建更好的软件。开始使用 LaunchDarkly!

Twitter Follow

平台支持

平台 支持情况
Android
iOS
MacOS
Web
Linux
Windows

快速开始

请参考 SDK 文档 获取如何开始使用该 SDK 的说明。

了解更多

阅读我们的 文档 以获取配置和使用 LaunchDarkly 的深入说明。您也可以直接前往 此 SDK 的完整参考指南代码生成的 API 文档

测试

我们为所有 SDK 运行集成测试,使用集中式测试框架。这种方法使我们能够跨 SDK 测试一致性。这些测试涵盖了 SDK 中的每个方法,并验证事件发送、标志评估、流重新连接等方面是否正确工作。

贡献

我们鼓励来自社区的拉取请求和其他贡献。请阅读我们的 贡献指南 了解如何为此 SDK 做出贡献。

关于 LaunchDarkly

  • LaunchDarkly 是一个功能管理平台。我们赋能所有团队交付并控制他们的软件。使用 LaunchDarkly,您可以:
    • 向一部分最终用户推出新功能,例如加入 beta 测试者组的用户,并从真实用例中收集反馈和错误报告。
    • 逐步向越来越多的客户推出功能,并跟踪该功能对关键指标的影响。例如,拥有功能 A 和功能 B 的客户完成购买的可能性有多大?
    • 关闭在生产环境中引起性能问题的功能,而无需重新部署或甚至重启应用程序。
    • 根据最终用户的属性(如支付计划)授予对某些功能的访问权限。(例如,“黄金”计划的客户比“银色”计划的客户有更多功能访问权限。)
    • 在不完全下线的情况下停用应用程序的部分以进行维护。
  • LaunchDarkly 提供了广泛语言和技术的功能标记 SDK。请参阅我们的 SDK 文档 获取完整列表。
  • 探索 LaunchDarkly

示例代码

下面是一个完整的示例代码,展示了如何在 Flutter 应用程序中使用 launchdarkly_flutter_client_sdk 插件来管理功能标记。

import 'package:flutter/material.dart';
import 'package:launchdarkly_flutter_client_sdk/launchdarkly_flutter_client_sdk.dart';
import 'package:provider/provider.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return Provider<LDClient>(
      create: (_) => LDClient(
        LDConfig(
          // 使用环境变量设置凭据
          CredentialSource.fromEnvironment(),
          AutoEnvAttributes.enabled,
        ),
        LDContextBuilder().kind('user', 'user-key').build(),
      ),
      dispose: (_, client) => client.close(),
      child: MaterialApp(
        title: 'LaunchDarkly Example',
        theme: ThemeData(
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
          useMaterial3: true,
        ),
        home: const MyHomePage(title: 'LaunchDarkly Example'),
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class FlagProviderString extends StreamProvider<String> {
  FlagProviderString({
    super.key,
    required LDClient client,
    required String flagKey,
    required String defaultValue,
    required Widget child,
  }) : super(
          create: (context) => client.flagChanges
              .where((element) => element.keys.contains(flagKey))
              .map((event) => client.stringVariation(flagKey, defaultValue)),
          initialData: client.stringVariation(flagKey, defaultValue),
          child: child,
        );
}

class _MyHomePageState extends State<MyHomePage> {
  final _userKeyController = TextEditingController(text: 'user-key');
  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: FutureBuilder(
        future: Provider.of<LDClient>(context, listen: false)
            .start()
            .timeout(const Duration(seconds: 5), onTimeout: () => true)
            .then((value) => true),
        builder: (context, loaded) => loaded.data ?? false
            ? Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Form(
                      key: _formKey,
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          TextFormField(
                            validator: (value) {
                              if (value == null || value.isEmpty) {
                                return 'Please enter a user key';
                              }
                              return null;
                            },
                            controller: _userKeyController,
                          ),
                          Padding(
                            padding: const EdgeInsets.symmetric(vertical: 16),
                            child: ElevatedButton(
                              onPressed: () {
                                if (_formKey.currentState!.validate()) {
                                  final client = Provider.of<LDClient>(
                                      context,
                                      listen: false);

                                  client
                                      .identify(LDContextBuilder()
                                          .kind('user', _userKeyController.text)
                                          .build())
                                      .then((value) {
                                    ScaffoldMessenger.of(context).showSnackBar(
                                      const SnackBar(content: Text('Identify complete')),
                                    );
                                  });
                                }
                              },
                              child: const Text('Identify'),
                            ),
                          ),
                        ],
                      ),
                    ),
                    FlagProviderString(
                      client: Provider.of<LDClient>(context, listen: false),
                      flagKey: 'string-flag',
                      defaultValue: 'default-value',
                      child: Consumer<String>(
                        builder: (context, flagValue, _) =>
                            Text('flag value: $flagValue'),
                      ),
                    ),
                  ],
                ),
              )
            : const CircularProgressIndicator(),
      ),
    );
  }
}

代码解释

  1. 初始化 SDK:在 main.dart 文件中,通过 Provider 包装整个应用程序,确保 LDClient 在应用程序生命周期内保持不变。
  2. 配置 SDK:使用 LDConfigLDContextBuilder 初始化 LDClient,并通过环境变量设置凭据。
  3. 启动 SDK:使用 FutureBuilder 等待 SDK 启动完成,或者超时后继续执行。
  4. 标识用户:通过表单输入用户键,并调用 identify 方法更新当前用户。
  5. 监听功能标记变化:使用 FlagProviderString 监听特定功能标记的变化,并显示其值。

通过以上步骤,您可以轻松地在 Flutter 应用程序中集成和使用 LaunchDarkly 的功能管理平台。


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

1 回复

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


当然,以下是如何在Flutter项目中使用launchdarkly_flutter_client_sdk插件来进行特性管理的代码示例。这个插件允许你与LaunchDarkly服务集成,从而进行远程特性标志(feature flags)的管理。

1. 添加依赖

首先,你需要在pubspec.yaml文件中添加launchdarkly_flutter_client_sdk依赖:

dependencies:
  flutter:
    sdk: flutter
  launchdarkly_flutter_client_sdk: ^x.y.z  # 替换为最新版本号

2. 初始化LaunchDarkly客户端

在你的Flutter项目的main.dart文件或类似的入口文件中,初始化LaunchDarkly客户端。你需要提供SDK密钥(SDK Key)和相关的配置。

import 'package:flutter/material.dart';
import 'package:launchdarkly_flutter_client_sdk/launchdarkly_flutter_client_sdk.dart';

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

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

class _MyAppState extends State<MyApp> {
  LDClient? ldClient;

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

  void initLaunchDarkly() async {
    // 替换为你的SDK密钥
    final String sdkKey = "your-sdk-key-here";
    
    // 创建LDConfig对象,可以根据需要添加更多配置
    final LDConfig config = LDConfig.builder()
      ..withStream(true) // 启用实时更新
      ..build();

    // 初始化LDClient
    ldClient = await LDClient.init(sdkKey, config);

    // 监听特性标志的变化(可选)
    ldClient?.addListener((flagKey, flagValue, oldValue) {
      print("Flag ${flagKey} changed from $oldValue to $flagValue");
    });

    // 检查某个特性标志的值(示例)
    checkFeatureFlag();
  }

  void checkFeatureFlag() async {
    if (ldClient != null) {
      final bool featureEnabled = await ldClient!.boolValue(forKey: "my-feature-flag");
      print("My Feature Flag is enabled: $featureEnabled");
      
      // 根据特性标志的值更新UI(示例)
      // setState(() {
      //   // 更新UI逻辑
      // });
    }
  }

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

3. 使用特性标志

在你的Flutter应用中,你可以在任何地方使用ldClient来获取特性标志的值,并根据这些值来改变应用的行为或UI。

// 假设你有一个按钮,根据特性标志的值来决定是否显示
Widget buildButton() {
  return FutureBuilder<bool>(
    future: ldClient!.boolValue(forKey: "show-button-feature-flag"),
    builder: (context, snapshot) {
      if (snapshot.connectionState == ConnectionState.done) {
        bool showButton = snapshot.data ?? false;
        return showButton
            ? ElevatedButton(
                onPressed: () {
                  // 按钮点击事件
                },
                child: Text('Click Me!'))
            : Container(); // 如果特性标志为false,则不显示按钮
      } else {
        return Container(); // 等待特性标志值加载完成
      }
    },
  );
}

4. 运行应用

确保你的LaunchDarkly项目已经设置好相应的特性标志,并且SDK密钥是有效的。然后运行你的Flutter应用,你应该能够在控制台看到特性标志的值,并且UI会根据这些值进行相应更新。

这个示例展示了如何初始化LaunchDarkly客户端、监听特性标志的变化以及在Flutter应用中使用特性标志来改变UI。根据你的需求,你可以进一步扩展这些功能。

回到顶部