Bootstrap

Flutter-状态管理(Provider)

前言

Provider 是状态管理的官方推荐的状态管理的库.可以实现跨组件数据传输

pub地址:provider | Flutter package

github地址:https://github.com/rrousselGit/provider

Provider 是什么?

Provider 是一种依赖注入工具,用于在 Flutter widget 树中管理和共享状态。它基于 InheritedWidget,通过将状态提升到应用程序顶层,解决了手动传递数据的复杂性。

核心组件

  1. Provider
    基础的依赖注入工具,常用的类型包括:

    • ChangeNotifierProvider
    • Provider
    • FutureProvider
    • StreamProvider
    • ProxyProvider
  2. ChangeNotifier
    ChangeNotifier 是一个支持监听的类,提供了管理状态和通知更新的能力。

  3. Consumer
    Consumer 用于监听 Provider 数据的变化,并更新 UI。

  4. Selector
    Selector 用于选择和监听数据中的某一部分,优化重建逻辑。

什么时候使用 Provider?

  1. 状态需要跨组件共享。
  2. 避免深层嵌套的数据传递(“prop drilling”)。
  3. 数据需要响应用户操作而更新。

使用方式

第一步:添加依赖

flutter pub add provider

第二步:设置 Provider

在应用顶层设置 Provider。可以使用 MultiProvider 或单独的 ChangeNotifierProvider

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
 
// 启动应用
void main() {
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => Counter()),
      ],
      child: MyApp(),
    ),
  );
}
 
// Counter 状态类
class Counter extends ChangeNotifier {
  int _count = 0;
 
  int get count => _count;
 
  void increment() {
    _count++;
    notifyListeners(); // 通知 UI 更新
  }
}
 
// 主应用
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

第三步:创建状态类

Provider 通常结合 ChangeNotifier 使用,状态类需要继承 ChangeNotifier,并在状态发生变化时调用 notifyListeners() 通知监听器更新

class Counter extends ChangeNotifier {
  int _count = 0;
 
  int get count => _count;
 
  void increment() {
    _count++;
    notifyListeners(); // 通知 UI 更新
  }
}

第四步:使用状态

通过 Consumer 或 Provider.of 在 widget 树中使用状态数据。

使用 Consumer
class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Provider Example")),
      body: Center(
        child: Consumer<Counter>(
          builder: (context, counter, child) {
            return Text(
              'Count: ${counter.count}',
              style: TextStyle(fontSize: 24),
            );
          },
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => context.read<Counter>().increment(),
        child: Icon(Icons.add),
      ),
    );
  }
}
使用 Provider.of
class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final counter = Provider.of<Counter>(context);
 
    return Scaffold(
      appBar: AppBar(title: Text("Provider Example")),
      body: Center(
        child: Text(
          'Count: ${counter.count}',
          style: TextStyle(fontSize: 24),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: counter.increment,
        child: Icon(Icons.add),
      ),
    );
  }
}

进阶用法

1. 多个 Provider

当需要管理多个状态时,可以使用 MultiProvider

MultiProvider(
  providers: [
    ChangeNotifierProvider(create: (_) => Counter()),
    ChangeNotifierProvider(create: (_) => AnotherState()),
  ],
  child: MyApp(),
);

2. 动态依赖注入

使用 ProxyProvider 动态注入其他 Provider 提供的依赖:

MultiProvider(
  providers: [
    Provider(create: (_) => Repository()),
    ProxyProvider<Repository, Service>(
      update: (context, repository, previousService) => Service(repository),
    ),
  ],
  child: MyApp(),
);

3. 优化性能

使用 Selector 优化监听,避免不必要的 UI 重建:

Selector<Counter, int>(
  selector: (context, counter) => counter.count,
  builder: (context, count, child) {
    return Text('Count: $count');
  },
);

;