Flutter功能实验与特性管理插件devcycle_flutter_client_sdk的使用

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

Flutter功能实验与特性管理插件devcycle_flutter_client_sdk的使用

DevCycle Flutter Client SDK

DevCycle Flutter Client SDK 是一个用于在 Flutter 应用中进行功能实验和特性管理的插件。它利用 DevCycle 的 Client SDK API 进行用户分段和分桶,通过全球分布的边缘节点提供快速响应时间。

支持的平台

  • Flutter: 最低版本 2.5.0
  • iOS: 最低版本 13.7
  • Android: 最低 API 版本 26

其他 Flutter 平台目前不支持此 SDK。

安装

使用 Flutter CLI

你可以通过以下命令将 SDK 安装到你的 Flutter 项目中:

flutter pub add devcycle_flutter_client_sdk

修改 pubspec.yaml

你也可以通过在 pubspec.yaml 文件中添加以下内容来安装 SDK:

dependencies:
  devcycle_flutter_client_sdk: ^1.7.0

然后运行以下命令:

flutter pub get

使用

更多使用文档可以参考 DevCycle 官方文档

示例代码

以下是一个完整的示例代码,展示了如何在 Flutter 应用中使用 devcycle_flutter_client_sdk 插件。

import 'package:flutter/material.dart';
import 'package:logger/logger.dart';
import 'dart:async';
import 'dart:convert';

import 'package:flutter/services.dart';
import 'package:devcycle_flutter_client_sdk/devcycle_flutter_client_sdk.dart';

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

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

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final _logger = Logger();
  String _platformVersion = 'Unknown';
  String _displayValue = '';
  String _variableValue = '';
  bool _booleanValue = false;
  num _integerValue = 0;
  num _doubleValue = 0.0;
  var _jsonArrayValue = '';
  var _jsonObjectValue = '';

  var encodedJsonArray = '''
  [
    {"score": 40},
    {"score": 80}
  ]
''';
  var encodedJsonObject = '''
  {
    "score1": 40,
    "score2": 80
  }
''';

  final _devCycleClient = DevCycleClientBuilder()
      .sdkKey('<DEVCYCLE_MOBILE_SDK_KEY>')
      .user(DevCycleUserBuilder().userId('123').build())
      .options(DevCycleOptionsBuilder().logLevel(LogLevel.debug).build())
      .build();

  @override
  void initState() {
    super.initState();
    initPlatformState();
    initVariable();
  }

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initPlatformState() async {
    String platformVersion;
    // Platform messages may fail, so we use a try/catch PlatformException.
    // We also handle the message potentially returning null.
    try {
      platformVersion = await _devCycleClient.getPlatformVersion() ??
          'Unknown platform version';
    } on PlatformException {
      platformVersion = 'Failed to get platform version.';
    }

    // If the widget was removed from the tree while the asynchronous platform
    // message was in flight, we want to discard the reply rather than calling
    // setState to update our non-existent appearance.
    if (!mounted) return;

    setState(() {
      _platformVersion = platformVersion;
    });
  }

  Future<void> initVariable() async {
    // Wait for client to initialize before fetching variables
    _devCycleClient.onInitialized(([error]) async {
      setState(() {
        _displayValue = error ?? 'DevCycle Client initialized';
      });

      final variable =
          await _devCycleClient.variable('string-variable', 'Default Value');
      setState(() {
        _variableValue = variable.value;
      });
      variable.onUpdate((updatedValue) {
        setState(() {
          _variableValue = updatedValue;
        });
      });

      final booleanVariable =
          await _devCycleClient.variable('boolean-variable', false);
      setState(() {
        _booleanValue = booleanVariable.value;
      });
      booleanVariable.onUpdate((updatedValue) {
        setState(() {
          _booleanValue = updatedValue;
        });
      });

      final integerVariable =
          await _devCycleClient.variable('integer-variable', 188);
      setState(() {
        _integerValue = integerVariable.value;
      });
      integerVariable.onUpdate((updatedValue) {
        setState(() {
          _integerValue = updatedValue;
        });
      });

      final doubleVariable =
          await _devCycleClient.variable('decimal-variable', 1.88);
      setState(() {
        _doubleValue = doubleVariable.value;
      });
      doubleVariable.onUpdate((updatedValue) {
        setState(() {
          _doubleValue = updatedValue;
        });
      });

      final jsonArrayVariable = await _devCycleClient.variable(
          'json-array-variable', jsonDecode(encodedJsonArray));
      setState(() {
        _jsonArrayValue = jsonEncode(jsonArrayVariable.value);
      });
      jsonArrayVariable.onUpdate((updatedValue) {
        setState(() {
          _jsonArrayValue = jsonEncode(updatedValue);
        });
      });

      final jsonObjectVariable = await _devCycleClient.variable(
          'json-object-variable', jsonDecode(encodedJsonObject));
      setState(() {
        _jsonObjectValue = jsonEncode(jsonObjectVariable.value);
      });
      jsonObjectVariable.onUpdate((updatedValue) {
        setState(() {
          _jsonObjectValue = jsonEncode(updatedValue);
        });
      });
    });
  }

  void resetUser() {
    _devCycleClient.resetUser();
    setState(() {
      _displayValue = 'User reset!';
    });
  }

  void identifyUser() {
    DevCycleUser testUser =
        DevCycleUserBuilder().userId('test_user_123').build();
    _devCycleClient.identifyUser(testUser, ((err, variables) {
      if (err != null) {
        setState(() {
          _displayValue = err;
        });
      } else {
        _logger.d(variables.values
            .map((variable) => "${variable.key}: ${variable.value}")
            .toString());
      }
    }));
    setState(() {
      _displayValue = 'Identified user: \n${testUser.toString()}';
    });
  }

  void identifyAnonUser() {
    DevCycleUser anonUser = DevCycleUserBuilder().isAnonymous(true).build();
    _devCycleClient.identifyUser(anonUser);
    setState(() {
      _displayValue = 'Identified user: \n${anonUser.toString()}';
    });
  }

  void trackEvent() {
    DevCycleEvent event = DevCycleEventBuilder()
        .target('target-str')
        .type('flutter-test')
        .value(10.0)
        .metaData({'custom_key': 'value'}).build();
    _devCycleClient.track(event);
    setState(() {
      _displayValue = 'Tracked event: \n${event.toString()}';
    });
  }

  void showAllFeatures() async {
    Map<String, DVCFeature> features = await _devCycleClient.allFeatures();
    setState(() {
      _displayValue = 'All features: \n${features.keys.toString()}';
    });
  }

  void flushEvents() {
    _devCycleClient.flushEvents(([error]) {
      setState(() {
        _displayValue = error ?? 'Flushed events';
      });
    });
  }

  void showAllVariables() async {
    Map<String, DVCVariable> variables = await _devCycleClient.allVariables();
    setState(() {
      _displayValue =
          'All variables: \n${variables.values.map((variable) => "${variable.key}: ${variable.value}").toString()}';
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app'),
        ),
        body: Center(
            child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text("Value: $_variableValue"),
            Text("Value: $_booleanValue"),
            Text("Value: $_integerValue"),
            Text("Value: $_doubleValue"),
            Text("Value: $_jsonArrayValue"),
            Text("Value: $_jsonObjectValue"),
            Text('Running on: $_platformVersion\n'),
            Icon(
              Icons.star,
              color: _booleanValue ? Colors.blue[500] : Colors.red[500],
            ),
            _booleanValue
                ? const Icon(
                    Icons.sentiment_very_satisfied,
                    color: Colors.grey,
                  )
                : const Icon(
                    Icons.sentiment_very_dissatisfied,
                    color: Colors.grey,
                  ),
            ElevatedButton(
                onPressed: showAllFeatures, child: const Text('All Features')),
            ElevatedButton(
                onPressed: showAllVariables,
                child: const Text('All Variables')),
            ElevatedButton(
                onPressed: identifyUser, child: const Text('Identify User')),
            ElevatedButton(
                onPressed: identifyAnonUser,
                child: const Text('Identify Anonymous User')),
            ElevatedButton(
                onPressed: resetUser, child: const Text('Reset User')),
            ElevatedButton(
                onPressed: trackEvent, child: const Text('Track Event')),
            ElevatedButton(
                onPressed: flushEvents, child: const Text('FlushEvents')),
            Text(_displayValue)
          ],
        )),
      ),
    );
  }
}

说明

  1. 初始化 SDK

    • 使用 DevCycleClientBuilder 构建 DevCycleClient 实例,并设置 SDK 密钥、用户信息和日志级别。
    • initState 方法中调用 initPlatformStateinitVariable 方法初始化平台状态和变量。
  2. 获取平台版本

    • getPlatformVersion 方法用于获取当前平台的版本信息。
  3. 初始化变量

    • onInitialized 方法用于等待客户端初始化完成后再获取变量值。
    • 使用 variable 方法获取不同类型的变量(字符串、布尔值、整数、浮点数、JSON 数组和 JSON 对象)。
  4. 重置用户

    • resetUser 方法用于重置当前用户。
  5. 识别用户

    • identifyUser 方法用于识别特定用户。
    • identifyAnonUser 方法用于识别匿名用户。
  6. 跟踪事件

    • trackEvent 方法用于跟踪自定义事件。
  7. 显示所有功能和变量

    • showAllFeatures 方法用于显示所有功能。
    • showAllVariables 方法用于显示所有变量。
  8. 刷新事件

    • flushEvents 方法用于刷新已跟踪的事件。

通过以上步骤,你可以在 Flutter 应用中有效地使用 devcycle_flutter_client_sdk 插件进行功能实验和特性管理。


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

1 回复

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


当然,以下是一个关于如何在Flutter项目中集成和使用devcycle_flutter_client_sdk插件来进行功能实验与特性管理的示例代码。这个示例将展示如何初始化DevCycle客户端、获取一个功能标志的值,并根据该值动态地改变应用行为。

步骤 1: 添加依赖

首先,在你的pubspec.yaml文件中添加devcycle_flutter_client_sdk依赖:

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

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

步骤 2: 初始化DevCycle客户端

在你的Flutter应用的入口文件(通常是main.dart)中初始化DevCycle客户端。你需要提供你的DevCycle项目ID和SDK密钥。

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

void main() {
  // 初始化DevCycle客户端
  DevCycleFlutterClient.init(
    projectId: '你的项目ID',  // 替换为你的DevCycle项目ID
    sdkKey: '你的SDK密钥',    // 替换为你的DevCycle SDK密钥
  );

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter DevCycle Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

步骤 3: 获取功能标志的值

在你的主页面或任何需要的页面中,你可以使用DevCycle客户端来获取功能标志的值。

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

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String? featureFlagValue;

  @override
  void initState() {
    super.initState();
    // 获取功能标志的值,这里假设功能标志的键是'new_feature'
    DevCycleFlutterClient.getVariableValue(
      key: 'new_feature',
      defaultValue: 'false',  // 提供一个默认值以防DevCycle无法获取到值
      onSuccess: (value) {
        setState(() {
          featureFlagValue = value;
        });
      },
      onError: (error) {
        print('Error fetching feature flag: $error');
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('DevCycle Feature Flag Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'New Feature Enabled:',
              style: TextStyle(fontSize: 20),
            ),
            Text(
              featureFlagValue ?? 'Loading...',
              style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
            ),
          ],
        ),
      ),
    );
  }
}

步骤 4: 根据功能标志的值改变应用行为

你可以根据获取到的功能标志的值来改变应用的行为。例如,如果new_feature标志为true,你可以显示一个新的UI组件或启用新的功能。

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text('DevCycle Feature Flag Demo'),
    ),
    body: Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text(
            'New Feature Enabled:',
            style: TextStyle(fontSize: 20),
          ),
          Text(
            featureFlagValue ?? 'Loading...',
            style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
          ),
          if (featureFlagValue == 'true') ...[
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                // 这里放置新功能的相关代码
                print('New feature is enabled!');
              },
              child: Text('Use New Feature'),
            ),
          ],
        ],
      ),
    ),
  );
}

以上代码展示了如何在Flutter项目中集成和使用devcycle_flutter_client_sdk来进行功能实验与特性管理。你可以根据需要进一步扩展和修改这些代码以适应你的应用需求。

回到顶部