likes
comments
collection
share

详细了解flutter中provider的工作原理

作者站长头像
站长
· 阅读数 38

让我们深入解析一下Provider在Flutter中的工作原理,特别是如何利用InheritedWidget实现高效的状态管理。

Provider的工作原理

Provider作为Flutter中一个流行的状态管理解决方案,其核心依赖于InheritedWidget来实现状态共享。以下是Provider工作原理的详细解析:

1. ChangeNotifier与状态管理

ChangeNotifier是一个简单的类,它提供了监听器的注册和通知功能。通过notifyListeners方法,我们可以通知所有注册的监听器状态已经发生了变化。

dart
复制代码
class Counter with ChangeNotifier {
  int _count = 0;

  int get count => _count;

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

2. ChangeNotifierProvider提供状态

ChangeNotifierProvider是一个InheritedNotifier,它将ChangeNotifier实例插入到Widget树中,并负责创建和销毁状态对象。ChangeNotifierProvider的主要作用是将状态对象提供给子Widget。

dart
复制代码
ChangeNotifierProvider(
  create: (context) => Counter(),
  child: MyApp(),
)

3. InheritedNotifier的实现

InheritedNotifier继承自InheritedWidget,并包含一个Listenable(通常是ChangeNotifier),它负责监听状态变化,并在状态变化时触发重建。

dart
复制代码
class InheritedNotifier<T extends Listenable> extends InheritedWidget {
  final T notifier;

  InheritedNotifier({
    Key? key,
    required this.notifier,
    required Widget child,
  }) : super(key: key, child: child);

  @override
  bool updateShouldNotify(InheritedNotifier<T> oldWidget) {
    return oldWidget.notifier != notifier;
  }
}

4. ConsumerProvider.of访问状态

子Widget可以通过Provider.of方法直接访问状态,也可以通过Consumer小部件监听状态变化。Consumer小部件会在状态变化时自动重建,从而更新UI。

dart
复制代码
// 直接访问状态
final counter = Provider.of<Counter>(context);

// 监听状态变化
Consumer<Counter>(
  builder: (context, counter, child) {
    return Text('${counter.count}');
  },
)

源码解析

让我们深入解析一下ChangeNotifierProvider的源码实现:

  1. ChangeNotifierProvider ChangeNotifierProvider是一个InheritedNotifier,它将ChangeNotifierInheritedWidget结合起来。

    dart
    复制代码
    class ChangeNotifierProvider<T extends ChangeNotifier> extends InheritedNotifier<T> {
      ChangeNotifierProvider({
        Key? key,
        required T Function(BuildContext context) create,
        required Widget child,
      }) : super(key: key, notifier: create(context), child: child);
    
      static T of<T extends ChangeNotifier>(BuildContext context) {
        final provider = context.dependOnInheritedWidgetOfExactType<ChangeNotifierProvider<T>>();
        return provider!.notifier!;
      }
    }
    
  2. InheritedNotifier InheritedNotifier继承自InheritedWidget,并包含一个Listenable(通常是ChangeNotifier)。

    dart
    复制代码
    class InheritedNotifier<T extends Listenable> extends InheritedWidget {
      final T notifier;
    
      InheritedNotifier({
        Key? key,
        required this.notifier,
        required Widget child,
      }) : super(key: key, child: child);
    
      @override
      bool updateShouldNotify(InheritedNotifier<T> oldWidget) {
        return oldWidget.notifier != notifier;
      }
    }
    

完整示例

以下是一个完整的Flutter应用示例,展示了如何使用Provider进行状态管理:

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: CounterPage(),
    );
  }
}

class CounterPage 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: () => Provider.of<Counter>(context, listen: false).increment(),
        child: Icon(Icons.add),
      ),
    );
  }
}

Provider中,监听状态变化和通知状态变化的过程主要使用了观察者模式(Observer Pattern) 。此外,还结合了**依赖注入(Dependency Injection)**模式来简化状态管理。让我们深入分析这两个设计模式在Provider中的应用。

观察者模式

定义

观察者模式是一种行为型设计模式,定义了对象之间的一对多依赖关系,使得一个对象的状态发生变化时,所有依赖于它的对象都会得到通知并自动更新。这在需要自动通知并更新界面的时候非常有用。

Provider中的应用

Provider中,ChangeNotifier类实现了观察者模式。ChangeNotifier维护了一组监听器,当状态发生变化时,通过notifyListeners方法通知所有的监听器。

  1. 监听器的注册 当一个Widget需要监听状态变化时,它会将自身注册到ChangeNotifier中。

    dart
    复制代码
    class ChangeNotifier {
      List<VoidCallback> _listeners = [];
    
      void addListener(VoidCallback listener) {
        _listeners.add(listener);
      }
    
      void removeListener(VoidCallback listener) {
        _listeners.remove(listener);
      }
    
      void notifyListeners() {
        for (final listener in _listeners) {
          listener();
        }
      }
    }
    
  2. 状态变化的通知 当状态发生变化时,调用notifyListeners方法通知所有注册的监听器。

    dart
    复制代码
    class Counter with ChangeNotifier {
      int _count = 0;
    
      int get count => _count;
    
      void increment() {
        _count++;
        notifyListeners();
      }
    }
    

依赖注入模式

定义

依赖注入是一种设计模式,用于将对象的创建和依赖关系的管理外包给一个外部实体。这样可以减少类之间的耦合,使代码更容易测试和维护。

Provider中的应用

Provider中,通过ChangeNotifierProvider将状态对象注入到Widget树中,供子Widget使用。这种方式减少了Widget之间的依赖关系,使得状态管理更加清晰。

  1. 提供状态对象 ChangeNotifierProvider将状态对象插入到Widget树中,并提供给子Widget。

    dart
    复制代码
    ChangeNotifierProvider(
      create: (context) => Counter(),
      child: MyApp(),
    )
    
  2. 访问状态对象 子Widget可以通过Provider.of方法或Consumer小部件访问状态对象。

    dart
    复制代码
    final counter = Provider.of<Counter>(context);
    

总结

Provider在Flutter中的工作原理可以总结为以下几点:

  1. 状态管理:通过ChangeNotifier管理状态。
  2. 状态提供:通过ChangeNotifierProvider将状态对象插入到Widget树中。
  3. 状态访问:通过Provider.ofConsumer访问和监听状态变化。
  4. 状态变化通知:通过notifyListeners通知所有注册的监听器状态变化。
  • 观察者模式ChangeNotifier管理监听器并通知状态变化。
  • 依赖注入模式ChangeNotifierProvider提供状态对象并将其注入到Widget树中。

Provider中,监听状态变化和通知状态变化主要使用了观察者模式。依赖注入模式用于简化状态管理和减少组件之间的耦合。 这种机制结合了ChangeNotifierInheritedWidget的优点,提供了一种简洁且高效的状态管理方式,非常适合Flutter应用程序的开发。

转载自:https://juejin.cn/post/7382107891400261684
评论
请登录