Flutter神秘框架插件arcane_framework的使用

Flutter神秘框架插件arcane_framework的使用

Arcane Framework 是一个强大的 Dart 包,旨在为管理应用程序的关键服务(如日志记录、身份验证、安全存储、功能标志、主题等)提供一个健壮的架构。此框架非常适合构建需要动态配置和服务管理的可扩展应用。

功能

  • 服务管理:集中访问多个服务(日志记录、身份验证、主题等)。
  • 功能标志:使用 ArcaneFeatureFlags 动态启用或禁用功能。
  • 日志记录:通过 ArcaneLogger 轻松记录带有元数据、堆栈跟踪和不同日志级别的消息。
  • 身份验证:内置支持处理用户身份验证工作流。
  • 动态主题:使用 ArcaneReactiveTheme 切换浅色和深色主题。

开始使用

安装

  1. 将依赖项添加到您的 pubspec.yaml 文件:
dependencies:
  arcane_framework: <latest>
  1. 使用 ArcaneApp 小部件包装您的 MaterialAppCupertinoApp,并提供必要的服务和根小部件:
import 'package:arcane_framework/arcane_framework.dart';

void main() {
  runApp(
    ArcaneApp(
      services: [
        MyArcaneService.I,
      ],
      child: MyApp(...),
    ),
  );
}

使用

服务

Arcane Framework 提供了一种集中的方式来管理应用程序中的服务。这使得您可以轻松地访问和配置应用程序中的所有服务,而无需将它们传递给多个小部件。

以下是一个服务类的示例:

class FavoriteColorService extends ArcaneService {
  static final FavoriteColorService _instance = FavoriteColorService._internal();

  static FavoriteColorService get I => _instance;

  FavoriteColorService._internal();

  Color? get myFavoriteColor => _notifier.value;

  final ValueNotifier<Color?> _notifier = ValueNotifier<Color?>(null);

  ValueNotifier<Color?> get notifier => _notifier;

  void setMyFavoriteColor(Color? newValue) {
    if (_notifier.value != newValue) {
      _notifier.value = newValue;
    }

    notifyListeners();
  }
}

要注册服务,请将其实例添加到 ArcaneApp 的服务列表中:

ArcaneApp(
  services: [
    FavoriteColorService.I,
  ],
  child: MyApp(...),
),

可以通过直接引用(例如 FavoriteColorService.I.myFavoriteColor)或通过 BuildContext(例如 context.serviceOfType<FavoriteColorService>()?.myFavoriteColor)访问服务属性。如果服务包含 notifyListeners() 方法,任何引用服务属性的小部件将自动接收到更改通知。此外,可以添加监听器以观察值的变化。

FavoriteColorService.I.notifier.addListener(() {
  final Color? color = FavoriteColorService.I.myFavoriteColor;
  // 对值执行某些操作
});

功能标志

您可以使用内置的服务 ArcaneFeatureFlags 轻松管理功能标志。功能标志可用于在不同情况下启用或禁用应用程序的不同部分。例如,您可能希望仅在新功能完成开发和测试后启用它,同时仍然能够发布未完成的代码。您还可以利用功能标志启用应用程序中的不同模式(例如,“免费”与“付费”)。此外,它们可用于 A/B 测试。选项几乎是无限的。

首先,创建一个 enum 来定义您的功能:

enum Feature {
  awesomeFeature(true),
  prettyOkFeature(false),
  ;

  /// 确定在应用程序启动时是否默认启用给定的功能。功能可以在运行时启用或禁用,无论此值为何。
  final bool enabledAtStartup;

  const Feature(this.enabledAtStartup);
}

接下来,确保功能在启动时启用,通过在功能标志服务中注册它们:

void main() {
  WidgetsFlutterBinding.ensureInitialized();

  // 注册您将用于启用和禁用功能的枚举。
  for (final Feature feature in Feature.values) {
    if (feature.enabledAtStartup) Arcane.features.enableFeature(feature);
  }

  runApp(const ArcaneApp());
}

当您想要确定某个功能是否启用时,可以使用其中一个助手扩展:

// 通过枚举扩展
final bool isMyAwesomeFeatureEnabled = Feature.awesomeFeature.enabled;

// 通过 Arcane 功能标志服务
final bool isMyPrettyOkFeatureDisabled = Arcane.features.isDisabled(Feature.prettyOkFeature);

您也可以在运行时启用和禁用功能:

// 通过枚举扩展
Feature.awesomeFeature.disable();
Feature.prettyOkFeature.enable();

// 通过 Arcane 特性服务
Arcane.features.disableFeature(Feature.awesomeFeature);
Arcane.features.enableFeature(Feature.prettyOkFeature);

要获取当前启用的功能列表,请简单询问 Arcane 功能标志服务:

final List<Enum> enabledFeatures = Arcane.features.enabledFeatures;

还可以添加监听器以观察启用功能的变化。

Arcane.features.notifier.addListener(() {
  print("Features changed: ${Arcane.features.enabledFeatures}");
});

注意,可以在功能标志服务中注册多个不同的 Enum 类型,如有必要。

日志记录

Arcane Framework 提供了一个强大的日志系统,允许您轻松记录带有元数据、堆栈跟踪和不同日志级别的消息。框架还提供了轻松配置日志记录行为的方法(例如,是否显示堆栈跟踪)。

首先,创建一个或多个日志接口,扩展 LoggingInterface 基类:

class DebugConsole implements LoggingInterface {
  static final DebugConsole _instance = DebugConsole._internal();
  static DebugConsole get I => _instance;
  DebugConsole._internal();

  final bool _initialized = true;

  [@override](/user/override)
  bool get initialized => I._initialized;

  [@override](/user/override)
  void log(
    String message, {
    Map<String, dynamic>? metadata,
    Level? level,
    StackTrace? stackTrace,
  }) {
    debugPrint(
      "$message\n"
      "$metadata\n",
    );
  }

  [@override](/user/override)
  Future<LoggingInterface?> init() async => I;
}

接下来,将您的日志接口注册到 Arcane 日志服务:

// 注册您的日志接口
await Arcane.logger.registerInterfaces([
  DebugConsole.I,
]);

// 初始化已注册的日志接口
// 注意:此步骤可能延迟到用户已同意应用程序跟踪。
await Arcane.logger.initializeInterfaces();

最后,向日志消息添加任何其他持久的元数据(可选),然后记录一条消息:

// 向日志器添加持久元数据
Arcane.logger.addPersistentMetadata({
  "app_name": "My App",
  "environment": "production",
});

// 记录一条消息!
Arcane.log(
  "This is a debug message",
  level: Level.debug,
  module: "ModuleName",
  method: "MethodName",
  metadata: {"key": "value"},
  stackTrace: StackTrace.current,
);

可以同时注册多个日志接口。

重要提示:日志接口通常应在与日志服务注册之后进行初始化。这确保了在记录任何消息之前所有日志接口都已正确初始化。这通常应手动执行,以便适当地向用户提供即将被提示授予跟踪权限的消息(在 iOS 上)。

身份验证

Arcane Framework 提供了一个有用的接口,用于执行常见的身份验证任务,如注册、密码重置、登录、登出和启用调试模式。

首先,创建一个身份验证接口提供者并将其注册到 Arcane 身份验证模块:

import "package:arcane_framework/arcane_framework.dart";

typedef Credentials = ({String email, String password});

class DebugAuthInterface
  with ArcaneAuthAccountRegistration, ArcaneAuthPasswordManagement
  implements ArcaneAuthInterface {
  DebugAuthInterface._internal();

  static final ArcaneAuthInterface _instance = DebugAuthInterface._internal();
  static ArcaneAuthInterface get I => _instance;

  [@override](/user/override)
  Future<bool> get isSignedIn => Future.value(_isSignedIn);
  bool _isSignedIn = false;

  [@override](/user/override)
  Future<String?> get accessToken => isSignedIn.then(
        (loggedIn) => loggedIn ? "access_token" : null,
      );

  [@override](/user/override)
  Future<String?> get refreshToken => isSignedIn.then(
        (loggedIn) => loggedIn ? "refresh_token" : null,
      );

  [@override](/user/override)
  Future<Result<void, String>> logout() async {
    Arcane.log("Logging out");

    _isSignedIn = false;

    return Result.ok(null);
  }

  [@override](/user/override)
  Future<Result<void, String>> login<Credentials>({
    Credentials? input,
    Future<void> Function()? onLoggedIn,
  }) async {
    final bool alreadyLoggedIn = await isSignedIn;

    if (alreadyLoggedIn) return Result.ok(null);

    final credentials = input as ({String email, String password});

    final String email = credentials.email;
    final String password = credentials.password;

    Arcane.log("Logging in as $email using password $password");

    _isSignedIn = true;

    return Result.ok(null);
  }

  // 由 ArcaneAuthAccountRegistration 混入提供
  [@override](/user/override)
  Future<Result<String, String>> resendVerificationCode<T>({
    T? input,
  }) async {
    Arcane.log("Re-sending verification code to $input");
    return Result.ok("Code sent");
  }

  // 由 ArcaneAuthAccountRegistration 混入提供
  [@override](/user/override)
  Future<Result<SignUpStep, String>> register<Credentials>({
    Credentials? input,
  }) async {
    if (input != null) {
      final credentials = input as ({String email, String password});

      final String email = credentials.email;
      final String password = credentials.password;

      Arcane.log("Creating account for $email with password $password");
    }

    return Result.ok(SignUpStep.confirmSignUp);
  }

  // 由 ArcaneAuthAccountRegistration 混入提供
  [@override](/user/override)
  Future<Result<bool, String>> confirmSignup({
    String? username,
    String? confirmationCode,
  }) async {
    Arcane.log(
      "Confirming registration for $username with code $confirmationCode",
    );
    return Result.ok(true);
  }

  // 由 ArcaneAuthPasswordManagement 混入提供
  [@override](/user/override)
  Future<Result<bool, String>> resetPassword({
    String? email,
    String? newPassword,
    String? code,
  }) async {
    Arcane.log("Resetting password for $email");
    return Result.ok(true);
  }

  [@override](/user/override)
  Future<void> init() async {
    Arcane.log("Debug auth interface initialized.");
    return;
  }
}

// 注册一个接口以处理用户身份验证
await Arcane.auth.registerInterface(DebugAuthInterface.I);

一旦您的接口已创建并注册,您可以使用它来执行许多常见的身份验证任务:

// 使用 ArcaneAuthAccountRegistration 混入注册帐户
  final nextStep = await Arcane.auth.register<Credentials>(
    input: ("email": "user@example.com", "password": "password123"),
  );

// 使用 ArcaneAuthAccountRegistration 混入确认新注册的帐户
final accountConfirmed = await Arcane.auth.confirmSignup(
  email: "user@example.com",
  confirmationCode: "123456",
);

// 使用 ArcaneAuthAccountRegistration 混入重新发送验证代码
final response = await Arcane.auth.resendVerificationCode("user@example.com");

// 使用 ArcaneAuthPasswordManagement 混入发起密码重置流程
final passwordResetStarted = await Arcane.auth.resetPassword(
  email: "user@example.com",
  newPassword: "password456",
);

// 使用 ArcaneAuthPasswordManagement 混入确认密码重置
final passwordResetFinished = await Arcane.auth.resetPassword(
  email: "user@example.com",
  newPassword: "password456",
  confirmationCode: "123456",
);

// 使用电子邮件和密码登录
final result = await Arcane.auth.login(
  input: ("email": "user@example.com", "password": "password123"),
  onLoggedIn: () => Arcane.log("User logged in"),
);

// 登出
await Arcane.auth.logout();

动态主题

Arcane Framework 提供了一个简单的界面来管理应用程序中的主题,根据用户的系统设置动态切换浅色和深色主题,或者手动切换主题。

首先,在 Arcane 主题模块中注册您的 ThemeData 对象:

void main() {
  // 设置您的主题
  Arcane.theme
    ..setDarkTheme(darkTheme)
    ..setLightTheme(lightTheme);

  runApp(
    ArcaneApp(
      child: MainApp(),
    ),
  );
}

从这里开始,您可以遵循系统的主题:

// 遵循系统的主题模式
class MainApp extends StatefulWidget {
  const MainApp({super.key});

  [@override](/user/override)
  State<MainApp> createState() => _MainAppState();
}

class _MainAppState extends State<MainApp> {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return ArcaneApp(
      child: MaterialApp(
        theme: Arcane.theme.light,
        darkTheme: Arcane.theme.dark,
        themeMode: Arcane.theme.systemTheme.value,
      ),
    );
  }

  [@override](/user/override)
  void didChangeDependencies() {
    Arcane.theme.followSystemTheme(context);
    super.didChangeDependencies();
  }
}

或者手动控制主题模式:

// 手动控制主题模式
class MainApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return ArcaneApp(
      child: MaterialApp(
        theme: Arcane.theme.light,
        darkTheme: Arcane.theme.dark,
        themeMode: Arcane.theme.currentMode,
      ),
    );
  }
}

然后,您可以随时切换模式:

// 在浅色和深色主题之间切换
Arcane.theme.switchTheme();

// 获取当前主题数据
final ThemeData currentTheme = Arcane.theme.currentMode == ThemeMode.dark
  ? Arcane.theme.dark
  : Arcane.theme.light;

if (context.isDarkMode) {
  // 当暗模式激活时执行某些操作
}

// 设置自定义暗主题
Arcane.theme.setDarkTheme(customDarkTheme);

// 设置自定义浅主题
Arcane.theme.setLightTheme(customLightTheme);

示例代码

以下是完整的示例代码:

import "package:arcane_framework/arcane_framework.dart";
import "package:example/config.dart";
import "package:example/interfaces/debug_auth_interface.dart";
import "package:example/interfaces/debug_print_interface.dart";
import "package:example/services/demo_service.dart";
import "package:example/theme/theme.dart";
import "package:flutter/material.dart";

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  for (final Feature feature in Feature.values) {
    if (feature.enabledAtStartup) Arcane.features.enableFeature(feature);
  }

  await Future.wait([
    Arcane.logger.registerInterfaces([
      DebugPrint.I,
    ]),
    IdService.I.init(),
  ]);

  Arcane.logger.addPersistentMetadata({
    "session_id": IdService.I.sessionId.value,
  });

  await Arcane.auth.registerInterface(DebugAuthInterface.I);

  Arcane.theme
    ..setDarkTheme(darkTheme)
    ..setLightTheme(lightTheme);

  Arcane.log(
    "Initialization complete.",
    level: Level.info,
    module: "main",
    method: "main",
    metadata: {
      "ready": "true",
    },
  );

  runApp(const MainApp());
}

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

  [@override](/user/override)
  State<MainApp> createState() => _MainAppState();
}

class _MainAppState extends State<MainApp> {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return ArcaneApp(
      services: [
        IdService.I,
      ],
      child: MaterialApp(
        debugShowCheckedModeBanner: false,
        theme: Arcane.theme.light,
        darkTheme: Arcane.theme.dark,
        themeMode: Arcane.theme.currentMode,
        home: Scaffold(
          appBar: AppBar(
            title: const Text("Arcane Framework Example"),
            actions: [
              IconButton(
                icon: const Icon(Icons.contrast),
                onPressed: () {
                  Arcane.theme.switchTheme();
                  setState(() {});
                },
              ),
            ],
          ),
          body: const HomeScreen(),
        ),
      ),
    );
  }
}

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

  [@override](/user/override)
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  [@override](/user/override)
  Widget build(BuildContext context) {
    final bool isSignedIn = Arcane.auth.isSignedIn.value;
    return Center(
      child: SingleChildScrollView(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              "Authentication status: ${Arcane.auth.status.name}",
            ),
            if (isSignedIn)
              ElevatedButton(
                child: const Text("Sign out"),
                onPressed: () async {
                  await Arcane.auth.logOut(
                    onLoggedOut: () async {
                      setState(() {});
                    },
                  );
                },
              ),
            if (!isSignedIn)
              ElevatedButton(
                child: const Text("Sign in"),
                onPressed: () async {
                  await Arcane.auth.login<Map<String, String>>(
                    input: {
                      "email": "email",
                      "password": "password",
                    },
                    onLoggedIn: () async {
                      setState(() {});
                    },
                  );
                },
              ),
          ],
        ),
      ),
    );
  }
}

更多关于Flutter神秘框架插件arcane_framework的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter神秘框架插件arcane_framework的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,关于Flutter的神秘框架插件arcane_framework(请注意,这个框架名称是虚构的,因为在实际Flutter生态系统中并没有一个广泛认知的名为arcane_framework的插件),我可以提供一个假设性的使用案例代码,以展示如何集成和使用一个类似功能的插件。

假设arcane_framework是一个提供复杂UI组件、状态管理和数据绑定功能的Flutter插件,以下是一个简化的示例,展示如何在一个Flutter应用中集成并使用它。

1. 添加依赖

首先,你需要在pubspec.yaml文件中添加对arcane_framework的依赖(假设它存在于pub.dev或你的私有包仓库中):

dependencies:
  flutter:
    sdk: flutter
  arcane_framework: ^1.0.0  # 假设版本号

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

2. 初始化插件

在你的Flutter应用的入口文件(通常是main.dart)中,初始化arcane_framework

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

void main() {
  // 初始化arcane_framework
  ArcaneFramework.initialize();

  runApp(MyApp());
}

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

3. 使用插件功能

假设arcane_framework提供了一个复杂的UI组件MysticButton,我们可以这样使用它:

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

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

class _MyHomePageState extends State<MyHomePage> {
  final ArcaneController _controller = ArcaneController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Arcane Framework Demo'),
      ),
      body: Center(
        child: MysticButton(
          label: 'Press Me',
          onPressed: () {
            // 使用arcane_framework的功能,比如数据绑定或状态管理
            _controller.updateState(() {
              // 假设有一个状态变量
              print('Button pressed!');
            });
          },
          // 假设MysticButton有一些自定义属性
          color: Colors.purple,
          fontSize: 24,
        ),
      ),
    );
  }
}

// 假设ArcaneController是arcane_framework提供的一个状态管理类
class ArcaneController {
  void updateState(VoidCallback callback) {
    // 假设这里有一些状态管理的逻辑
    callback();
  }
}

4. 自定义组件(假设)

如果arcane_framework允许你创建自定义组件,你可以这样做:

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

class CustomMysticWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ArcaneContainer(
      decoration: BoxDecoration(color: Colors.amber),
      child: Text(
        'Hello from CustomMysticWidget!',
        style: TextStyle(fontSize: 20),
      ),
    );
  }
}

并在你的主页面中使用它:

// 在_MyHomePageState的build方法中添加
body: Center(
  child: Column(
    mainAxisAlignment: MainAxisAlignment.center,
    children: <Widget>[
      MysticButton(...), // 之前定义的按钮
      CustomMysticWidget(), // 自定义组件
    ],
  ),
),

注意

  • 由于arcane_framework是虚构的,上述代码是基于假设的功能和结构编写的。
  • 在实际开发中,你需要查阅arcane_framework(如果存在)的官方文档来了解其具体的API和使用方法。
  • Flutter社区提供了丰富的插件和框架,如果你正在寻找特定的功能,很可能已经有现成的解决方案可用。
回到顶部