Flutter服务提供插件flutter_service_provider的使用

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

Flutter服务提供插件flutter_service_provider的使用

flutter_service_provider 是一个用于在Flutter应用中管理依赖注入(Dependency Injection, DI)的插件。它基于 dart_service_provider 包,提供了几个有用的Widget来简化服务的注册和获取。本文将详细介绍如何使用 flutter_service_provider 插件,并提供一个完整的示例Demo。

主要特性

  1. Services<T>:构建服务提供器。
  2. ScopedServices<T>:创建一个服务作用域。
  3. ServiceConsumer<T>:将服务提供器传递给你的Widget构建器。
  4. ServiceInheritedWidget<T>:共享 IServiceProvider 实例给其子Widget。

获取 IServiceProvider 实例

  • 通过 Services.of<T>(context):从最近的 ServiceInheritedWidget<T> 获取 IServiceProvider 实例。注意,Services<T>ScopedServices<T> 会创建 ServiceInheritedWidget<T>
  • 通过 ServiceConsumer<T>IServiceProvider 实例会通过 builder 参数传递给子Widget。

单个根服务提供器

大多数应用程序只需要一个根服务提供器。在这种情况下,不需要指定泛型类型 T,或者使用相同的 T

Services();

ScopedServices();

ServiceConsumer();

多个根服务提供器

如果应用程序需要多个隔离的服务提供器,可以通过不同的泛型类型 T 来区分它们。

class RootServiceProvider1 {}

Services<RootServiceProvider1>();

ScopedServices<RootServiceProvider1>();

ServiceConsumer<RootServiceProvider1>();

// 获取 RootServiceProvider1 的 IServiceProvider 实例
final serviceProvider = Services.of<RootServiceProvider1>(context);

class RootServiceProvider2 {}

Services<RootServiceProvider2>();

ScopedServices<RootServiceProvider2>();

ServiceConsumer<RootServiceProvider2>();

// 获取 RootServiceProvider2 的 IServiceProvider 实例
final serviceProvider = Services.of<RootServiceProvider2>(context);

使用示例

以下是一个完整的示例,展示了如何在Flutter应用中使用 flutter_service_provider

1. main.dart
import 'package:dart_service_logger/dart_service_logger.dart';
import 'package:dart_service_provider/dart_service_provider.dart';
import 'package:flutter/material.dart';
import 'package:flutter_service_provider/flutter_service_provider.dart';

import 'src/services/services.dart';

void main() {
  runApp(
    // 使用 Services<T> 作为根
    Services(
      serviceConfig: (services) => services.addApplicationServices(),
      builder: (context, _) => const MyApp(),
    ),
  );
}

extension MyAppServiceCollectionExtensions on IServiceCollection {
  void addApplicationServices() {
    this
      ..addLogging(config: (b) => b.useLogger())
      ..addEnvironment(Environment(name: Environments.development))
      ..addHelloServices(); // 自定义服务注册
  }
}

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    final logger = Services.of(context).getRequiredLogger<MyApp>();
    logger.info("$MyApp is building");

    return MaterialApp(
      title: 'Flutter service Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: MyHomePage(title: "Flutter service example"),
    );
  }
}
2. MyHomePage
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  [@override](/user/override)
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late final String greetingMsg;
  late final String greetingMsg2;

  [@override](/user/override)
  void initState() {
    super.initState();

    // 获取服务提供器并获取服务实例
    final serviceProvider = Services.of(context);
    final helloService = serviceProvider.getRequiredService<SingletonHelloService>();
    final transientHelloService = serviceProvider.getRequiredService<TransientHelloService>();

    // 初始化问候语
    greetingMsg = helloService.greeting("Singleton");
    greetingMsg2 = transientHelloService.greeting("Transient");
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Text(greetingMsg), // 显示单例服务的问候语
            Text(greetingMsg2), // 显示瞬态服务的问候语
            ElevatedButton(
              onPressed: () {
                // 导航到带有作用域的服务页面
                Navigator.of(context).push(
                  MaterialPageRoute(
                    builder: (context) => ScopedServices(
                      builder: (context, _) => const ScopeFeatureWidget(),
                    ),
                  ),
                );
              },
              child: Text("Scoped Feature"),
            ),
          ],
        ),
      ),
    );
  }
}
3. ScopeFeatureWidget
class ScopeFeatureWidget extends StatelessWidget {
  const ScopeFeatureWidget({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    // 获取服务提供器并获取作用域内的服务实例
    final serviceProvider = Services.of(context);
    final service1 = serviceProvider.getRequiredService<ScopeHelloService>();
    final transientHelloService = serviceProvider.getRequiredService<TransientHelloService>();

    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text("$ScopeFeatureWidget"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Text(service1.greeting("Scope")), // 显示作用域服务的问候语
            Text(transientHelloService.greeting("Transient")), // 显示瞬态服务的问候语
            ServiceConsumer(
              builder: (context, p) {
                final service2 = p.getRequiredService<ScopeHelloService>();
                assert(identical(service1, service2),
                    "ServiceConsumer in ScopedServices widget should use the same IServiceProvider as ScopedServices");
                return Text(service2.greeting("Consumer")); // 确保作用域内服务一致
              },
            ),
            ElevatedButton(
              onPressed: () {
                // 导航到新路由并保持相同的作用域
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) {
                      return ServiceInheritedWidget(
                        provider: serviceProvider,
                        child: RouteAndScopedServicesWidget(),
                      );
                    },
                  ),
                );
              },
              child: Text("Same scope in new route"),
            ),
          ],
        ),
      ),
    );
  }
}
4. RouteAndScopedServicesWidget
class RouteAndScopedServicesWidget extends StatelessWidget {
  const RouteAndScopedServicesWidget({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    final p = Services.of(context);
    final service = p.getRequiredService<ScopeHelloService>();

    return Scaffold(
      appBar: AppBar(
        title: Text("Scoped services in new route"),
      ),
      body: Center(
        child: Text(service.greeting("New Route")), // 显示新路由中的作用域服务问候语
      ),
    );
  }
}

更多关于Flutter服务提供插件flutter_service_provider的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter服务提供插件flutter_service_provider的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,flutter_service_provider 插件允许你定义和共享服务,使得不同的部分(如Widgets、ViewModels等)能够访问和使用这些服务。虽然这个插件的具体实现可能因版本而异,且在实际开发中可能需要自定义服务,但我可以给你一个基本的示例来展示如何使用这个插件(假设它提供了类似依赖注入的功能)。

首先,确保你的pubspec.yaml文件中已经添加了flutter_service_provider依赖(注意:实际插件名称可能不同,这里仅为示例):

dependencies:
  flutter:
    sdk: flutter
  flutter_service_provider: ^x.y.z  # 替换为实际版本号

然后,运行flutter pub get来获取依赖。

接下来,我们将展示如何定义和使用一个服务。假设我们有一个简单的服务UserService,它提供了一个获取用户信息的方法。

定义服务

// user_service.dart
class UserService {
  String getUserInfo() {
    return 'Hello, this is user info!';
  }
}

提供服务

在你的应用中,你可能会有一个地方(如MaterialApp的顶层)来提供这个服务。

// main.dart
import 'package:flutter/material.dart';
import 'package:flutter_service_provider/flutter_service_provider.dart'; // 假设插件提供这样的API
import 'user_service.dart';

void main() {
  runApp(
    ServiceProvider<UserService>(
      create: (_) => UserService(),
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomeScreen(),
    );
  }
}

在这个例子中,ServiceProvider是一个假想的widget,用于提供UserService实例。实际使用时,你可能需要根据flutter_service_provider插件的实际API进行调整。

使用服务

在你的Widget中,你可以使用ServiceProvider.of(或类似方法,取决于实际插件的API)来获取服务实例。

// home_screen.dart
import 'package:flutter/material.dart';
import 'package:flutter_service_provider/flutter_service_provider.dart'; // 假设插件提供这样的API

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final UserService userService = ServiceProvider.of<UserService>(context);
    return Scaffold(
      appBar: AppBar(
        title: Text('Home Screen'),
      ),
      body: Center(
        child: Text(userService.getUserInfo()),
      ),
    );
  }
}

在这个例子中,ServiceProvider.of<UserService>(context)用于从上下文中获取UserService实例,并显示其返回的用户信息。

注意

  • 上面的代码是基于假设的flutter_service_provider插件的API。实际使用时,请查阅该插件的官方文档以获取正确的使用方法和API。
  • 如果flutter_service_provider插件不存在或不支持上述功能,你可能需要寻找其他依赖注入库(如get_itprovider)来实现类似的功能。
  • 始终确保你的依赖项是最新的,并且与你的Flutter SDK版本兼容。
回到顶部