Flutter子提供者管理插件flutter_sub_provider的使用

Flutter 子提供者管理插件 flutter_sub_provider 的使用

引言

flutter_sub_provider 插件允许通过 flutter_sub 创建合理的提供者依赖关系。它类似于 ProxyProvider,但当其依赖项发生变化时会完全重新创建。

动机

在使用 Provider 进行依赖注入时,通常需要创建一个依赖于另一个提供者的提供者。例如,一个 PaginationController 可能依赖于一个 HttpClient 来发起请求。在 flutter_sub_provider 中,这可能看起来像这样:

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SubProvider<HttpClient, PaginationController>(
      create: (context, httpClient) => PaginationController(client: httpClient),
      builder: (context, child) => /* ... */,
    );
  }
}

每当 HttpClient 发生变化时,一个新的 PaginationController 将被创建,并且小部件将使用新的控制器重建。底层,SubProvider 使用 SubValue 来管理 PaginationController

相比之下,等效的 ProxyProvider 代码如下:

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ProxyProvider<HttpClient, PaginationController>(
      update: (context, httpClient, paginationController) => paginationController..httpClient = httpClient,
      builder: (context, child) => /* ... */,
    );
  }
}

ProxyProvider 示例中,依赖项通过一个 setter 侧加载,并且当 HttpClient 发生变化时,PaginationController 就地更新。SubProvider 的方法有以下几个原因:

  1. 依赖项通过构造函数注入而不是通过 setter。这确保了我们的控制器始终以有效状态创建。
  2. 控制器的内部状态在 HTTP 客户端更改时重置。这确保我们不会有任何来自先前 HTTP 客户端的陈旧数据。
  3. HTTP 客户端可以是最终的或私有的。控制器保留对其变量的控制。

原则

flutter_sub 类似,flutter_sub_provider 建立在子的概念上——即紧凑版本的 StatefulWidget,它们创建、更新和销毁一个值。flutter_sub_provider 通过与 provider 集成来创建 SubProvider

SubProvider 扩展了相应的 Provider 类型,并添加了管理依赖项的功能。当依赖项发生变化时,SubProvider 会完全重新创建其管理的对象,以确保始终使用最新的依赖项。

为了简化理解,你可以想象 SubProvider 大致如下(实际上它更复杂):

class SubProvider<T, R> extends StatelessWidget {
  SubProvider({
    required this.create,
    required this.builder,
  });

  @override
  Widget build(BuildContext context) {
    final dependency = Provider.of<T>(context);
    return SubValue<R>.builder(
      create: (context, dependency),
      keys: [dependency],
      builder: (context, value) =>
        Provider<R>.value(
          value: value,
          builder: builder,
        ),
    );
  }
}

这段代码经过高度简化。要查看完整的实现,你可以查看 SubProvider

自定义子提供者

你可以直接在你的树中使用所有内置的子提供者。也可以扩展 SubProvider 来创建自己的可重用的子提供者。

要访问 SingleChildSubValue 和其他内部类型,可以通过导入 package:flutter_sub_provider/developer.dart

为了从我们之前的例子中创建一个可重用的子提供者,我们可以这样做:

class PaginationControllerProvider extends SubProvider<HttpClient, PaginationController> {
  PaginationControllerProvider({
    super.child,
    super.builder,
  }) : super(
        create: (context, httpClient) => PaginationController(client: httpClient),
  );
}

更多关于Flutter子提供者管理插件flutter_sub_provider的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

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


当然,我可以为你提供一个关于如何使用 flutter_sub_provider 插件的代码案例。flutter_sub_provider 是一个用于管理 Flutter 应用中状态子提供者的插件,通常与 provider 插件一起使用。它允许你在一个复杂的状态管理架构中轻松创建和管理子提供者。

以下是一个简单的示例,展示了如何在 Flutter 应用中使用 flutter_sub_provider

1. 添加依赖

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

dependencies:
  flutter:
    sdk: flutter
  provider: ^6.0.0  # 请确保使用最新版本
  flutter_sub_provider: ^0.4.0  # 请确保使用最新版本

2. 创建数据模型

创建一个简单的数据模型,例如 User

class User {
  final String name;
  final int age;

  User(this.name, this.age);
}

3. 创建 Provider 和 SubProvider

创建一个顶层 Provider 和一个 SubProvider

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter_sub_provider/flutter_sub_provider.dart';
import 'user_model.dart';  // 假设你的 User 类在这个文件中

class UserProvider with ChangeNotifier {
  User? _user;

  User? getUser() {
    return _user;
  }

  void setUser(User user) {
    _user = user;
    notifyListeners();
  }
}

class UserSubProvider with ChangeNotifier {
  User? _user;
  UserSubProvider(this._user);

  String get greeting() {
    return _user?.name != null ? "Hello, $_user!.name!" : "Hello, Guest!";
  }

  void setGreeting(String newGreeting) {
    // 通常情况下,这里不会直接设置 greeting,因为它是基于 user 的派生值
    // 这个方法只是为了演示如何调用 notifyListeners()
    notifyListeners();
  }
}

4. 使用 MultiProvider 包装应用

main.dart 中使用 MultiProvider 包装你的应用,并创建顶层 ProviderSubProvider

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'user_provider.dart';  // 假设你的 Provider 类在这个文件中

void main() {
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => UserProvider()),
        ChangeNotifierProxyProvider<UserProvider?, UserSubProvider>(
          create: (_ context, userProvider, previous) =>
              UserSubProvider(userProvider?.getUser() ?? null),
          update: (_, userProvider, previous) =>
              previous!...user = userProvider?.getUser(),
        ),
      ],
      child: MyApp(),
    ),
  );
}

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

5. 在 UI 中使用 Provider 和 SubProvider

在你的 UI 组件中使用 Consumerselect 来访问 ProviderSubProvider 的数据:

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

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter SubProvider Demo'),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Consumer<UserProvider>(
            builder: (context, userProvider, child) {
              return TextField(
                decoration: InputDecoration(labelText: 'Name'),
                onChanged: (value) {
                  userProvider.setUser(User(value, 25));  // 假设年龄固定为25
                },
              );
            },
          ),
          SizedBox(height: 20),
          Consumer<UserSubProvider>(
            builder: (context, userSubProvider, child) {
              return Text(userSubProvider.greeting);
            },
          ),
        ],
      ),
    );
  }
}

这个示例展示了如何在 Flutter 应用中使用 flutter_sub_provider 插件来管理子提供者。请注意,flutter_sub_provider 插件本身并不是 Flutter 官方库的一部分,因此在使用之前,请确保你已经正确添加了相应的依赖,并且该插件的 API 没有发生较大变化。

回到顶部