flutter中provider的进阶用法小结(一)

Provider 是 Flutter 中非常流行的状态管理库,它使得管理应用的状态变得简单高效。我们可以使用 Provider 来管理不同的状态,包括应用的全局状态、局部状态,甚至是依赖注入。

进阶用法

除了简单的状态共享,Provider 还可以用于一些更复杂的场景,比如多层嵌套的依赖注入自动销毁资源状态变化监听 等。接下来我将介绍一些进阶用法,帮助你更好地理解和应用 Provider


1. ChangeNotifierConsumer 使用

最常见的 Provider 使用模式是通过 ChangeNotifierConsumer 进行状态管理。在这个模式下,ChangeNotifier 充当了管理状态的角色,并在状态变化时通知界面更新。

示例:
dart 复制代码
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => Counter(),
      child: MyApp(),
    ),
  );
}

class Counter with ChangeNotifier {
  int _count = 0;

  int get count => _count;

  void increment() {
    _count++;
    notifyListeners(); // 通知消费者
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Provider Example')),
        body: Center(
          child: Consumer<Counter>(
            builder: (context, counter, child) {
              return Text('Counter: ${counter.count}', style: TextStyle(fontSize: 24));
            },
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () {
            context.read<Counter>().increment(); // 增加计数
          },
          child: Icon(Icons.add),
        ),
      ),
    );
  }
}
关键点:
  • ChangeNotifierProviderChangeNotifierProvider 是将 ChangeNotifier 放到 widget 树中的一个方式,Counter 继承了 ChangeNotifier,并且通过 notifyListeners() 来通知变化。
  • Consumer<Counter>Consumer 用来监听 Counter 对象的变化,当状态变化时,builder 方法会被重新调用,刷新 UI。

2. 使用 Selector 优化性能

SelectorProvider 提供的一个优化组件,它可以帮助你精确地选择你需要的部分状态并监听变化,从而避免不必要的 UI 重建。与 Consumer 不同,Selector 只会在所选状态发生变化时重新构建 UI。

示例:
dart 复制代码
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => Counter(),
      child: MyApp(),
    ),
  );
}

class Counter with ChangeNotifier {
  int _count = 0;
  int _otherValue = 0;

  int get count => _count;
  int get otherValue => _otherValue;

  void incrementCount() {
    _count++;
    notifyListeners();
  }

  void incrementOtherValue() {
    _otherValue++;
    notifyListeners();
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Provider Selector Example')),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Selector<Counter, int>(
                selector: (context, counter) => counter.count,  // 只选择 count 属性
                builder: (context, count, child) {
                  return Text('Counter: $count', style: TextStyle(fontSize: 24));
                },
              ),
              Selector<Counter, int>(
                selector: (context, counter) => counter.otherValue, // 只选择 otherValue 属性
                builder: (context, otherValue, child) {
                  return Text('Other Value: $otherValue', style: TextStyle(fontSize: 24));
                },
              ),
            ],
          ),
        ),
        floatingActionButton: Column(
          mainAxisAlignment: MainAxisAlignment.end,
          children: [
            FloatingActionButton(
              onPressed: () {
                context.read<Counter>().incrementCount(); // 增加计数
              },
              child: Icon(Icons.add),
            ),
            SizedBox(height: 10),
            FloatingActionButton(
              onPressed: () {
                context.read<Counter>().incrementOtherValue(); // 增加 otherValue
              },
              child: Icon(Icons.add_alert),
            ),
          ],
        ),
      ),
    );
  }
}
关键点:
  • SelectorSelector 允许你只选择并监听状态的一部分。当 count 发生变化时,只会重新构建显示 count 的部分,而 otherValue 的部分不会重新构建,避免不必要的 UI 更新。
  • 优化性能Selector 是一个性能优化工具,用来减少不必要的 widget 重建。

3. 使用 Provider 实现依赖注入

Provider 不仅适用于状态管理,它还可以用来实现依赖注入(DI)。通过 Provider,你可以在应用中创建并注入单例或多个不同类型的对象,使得它们在整个应用中共享。

示例:
dart 复制代码
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(
    MultiProvider(
      providers: [
        Provider(create: (context) => ApiService()),
        Provider(create: (context) => UserService(context.read<ApiService>())),
      ],
      child: MyApp(),
    ),
  );
}

class ApiService {
  String fetchData() {
    return "Data from API";
  }
}

class UserService {
  final ApiService apiService;

  UserService(this.apiService);

  String getUserData() {
    return apiService.fetchData();
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Provider Dependency Injection')),
        body: Center(
          child: Consumer<UserService>(
            builder: (context, userService, child) {
              return Text(userService.getUserData(), style: TextStyle(fontSize: 24));
            },
          ),
        ),
      ),
    );
  }
}
关键点:
  • MultiProvider :当你需要提供多个依赖项时,可以使用 MultiProvider。这里我们注入了两个服务:ApiServiceUserService
  • 依赖注入UserService 依赖于 ApiService,并且通过 context.read<ApiService>() 获取该服务。

4. 使用 FutureProviderStreamProvider

Provider 支持 FutureStream,你可以使用 FutureProvider 来异步加载数据,或使用 StreamProvider 来监听数据流。这对于异步操作(如网络请求或数据库查询)非常有用。

示例:使用 FutureProvider
dart 复制代码
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => DataProvider(),
      child: MyApp(),
    ),
  );
}

class DataProvider with ChangeNotifier {
  Future<String> fetchData() async {
    await Future.delayed(Duration(seconds: 2));
    return "Hello from the Future!";
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('FutureProvider Example')),
        body: Center(
          child: Consumer<DataProvider>(
            builder: (context, dataProvider, child) {
              return FutureProvider<String>(
                create: (_) => dataProvider.fetchData(),
                initialData: "Loading...",
                child: Builder(
                  builder: (context) {
                    String data = context.watch<String>();
                    return Text(data, style: TextStyle(fontSize: 24));
                  },
                ),
              );
            },
          ),
        ),
      ),
    );
  }
}
关键点:
  • FutureProviderFutureProvider 用来管理和提供一个异步操作(Future)的结果。你可以用它来在获取数据时显示加载状态。
  • 异步数据更新FutureProvider 会自动处理 Future 状态,提供初始数据并在数据加载完成后更新。

5. ProviderChangeNotifier 自动销毁资源

使用 ChangeNotifierProvider 时,可以确保在 Provider 不再使用时自动销毁其资源。通过设置 dispose 方法,可以确保当 Provider 不再被使用时自动清理资源,避免内存泄漏。

dart 复制代码
ChangeNotifierProvider(
  create: (context) => MyNotifier(),
  dispose: (context, notifier) => notifier.dispose(),
)

总结

Provider 在 Flutter 中非常强大,支持各种进阶用法。需要多加练习,特别是对于异步使用

相关推荐
wearegogog1231 小时前
基于 MATLAB 的卡尔曼滤波器实现,用于消除噪声并估算信号
前端·算法·matlab
Drawing stars1 小时前
JAVA后端 前端 大模型应用 学习路线
java·前端·学习
品克缤1 小时前
Element UI MessageBox 增加第三个按钮(DOM Hack 方案)
前端·javascript·vue.js
小二·1 小时前
Python Web 开发进阶实战:性能压测与调优 —— Locust + Prometheus + Grafana 构建高并发可观测系统
前端·python·prometheus
小沐°1 小时前
vue-设置不同环境的打包和运行
前端·javascript·vue.js
qq_419854052 小时前
CSS动效
前端·javascript·css
烛阴2 小时前
3D字体TextGeometry
前端·webgl·three.js
桜吹雪2 小时前
markstream-vue实战踩坑笔记
前端
云诗卡达3 小时前
Flutter安卓APP接入极光推送和本地通知
android·flutter
南村群童欺我老无力.3 小时前
Flutter应用鸿蒙迁移实战:性能优化与渐进式迁移指南
javascript·flutter·ci/cd·华为·性能优化·typescript·harmonyos