Flutter 47: 图解新的状态管理 Provider (二)

简介: 0 基础学习 Flutter,第四十七步:了解基本的 ListenableProvider / ValueListenableProvider / StreamProvider 状态管理方式!

      小菜前几天学习了一下新的状态管理框架 ProviderProvier 支持多种类型的状态管理方式,小菜继续学习其余几种;

ListenableProvider 方式

1. 数据绑定

  1. ListenableProvider({Key key, @required ValueBuilder builder, Disposer dispose, Widget child })

      通过构造器绑定数据并进行监听,当从 Widget Tree 中删除时 dispose 要销毁;注意:构造器 builder 不可为空;

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListenableProvider<User>(
        builder: (_) => User('Flutter', 0),
        child: MaterialApp(
            title: 'Flutter Demo',
            theme: ThemeData(primarySwatch: Colors.blue),
            home: MyHomePage(title: 'Peovider Demo')));
  }
}
  1. ListenableProvider.value({Key key, @required T listenable, Widget child })

      通过 .value 方式对数据进行监听 listenable

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListenableProvider<User>.value(
        listenable: User('Flutter', 0),
        child: MaterialApp(
            title: 'Flutter Demo',
            theme: ThemeData(primarySwatch: Colors.blue),
            home: MyHomePage(title: 'Peovider Demo')));
  }
}

2. 获取数据

      小菜在上一篇博客中未曾提及,基本所有的获取数据方式基本相同且均支持两种方式;

  1. Provider.of(context) 方式
class ProviderText extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final user = Provider.of<User>(context);
    return Text('${user.getName}');
  }
}
  1. Consumer Widget 构造器方式
class ProviderText extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Consumer<User>(builder: (context, user, _) {
        return Text(user.getName);
      });
  }
}

ValueListenableProvider 方式

      使用 ValueListenableProvider 方式时要注意,需要绑定的数据要继承自 ValueNotifier,并实现其构造方法,通过对 value 的操作进行更新;小菜新建一个 person 实体类进行操作;

// 基本数据类型
class StringBean extends ValueNotifier<String> {
  StringBean(String value) : super(value);
}

// 自定义实体类
class Person extends ValueNotifier<User> {
  Person(User value) : super(value);
  String get getPersonName => value.name;

  void setPersonName(String name) {
    value.name = name;
    notifyListeners();
  }
}

1. 绑定数据

  1. ValueListenableProvider({Key key, @required ValueBuilder> builder, UpdateShouldNotify updateShouldNotify, Widget child })

      通过构造器绑定数据并进行监听,且构造器 builder 不可为空;

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ValueListenableProvider<User>(
        builder: (_) => Person(User('person', 101)),
        child: MaterialApp(
            title: 'Flutter Demo',
            theme: ThemeData(primarySwatch: Colors.blue),
            home: MyHomePage(title: 'Peovider Demo')));
  }
}
  1. ValueListenableProvider.value({Key key, @required ValueListenable valueListenable, UpdateShouldNotify updateShouldNotify, Widget child })

      通过 .value 方式对数据进行绑定监听;

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ValueListenableProvider<User>.value(
        valueListenable: Person(User('person', 101)),
        child: MaterialApp(
            title: 'Flutter Demo',
            theme: ThemeData(primarySwatch: Colors.blue),
            home: MyHomePage(title: 'Peovider Demo')));
  }
}

2. 获取数据

      获取数据的方式与上述基本一致;

class ProviderText extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final number = Provider.of<String>(context);
    final person = Provider.of<User>(context);
    return Center(
        child: Column(children: <Widget>[
      Text('${number.toString()}==${person.getName}'),
      Consumer<User>(builder: (context, user, _) {
        return Text(user.getName);
      })
    ]));
  }
}

StreamProvider 方式

1. Stream 简介

      Stream 存在于 Dart:async 库中,主要用于处理异步操作;在 ListView 展示网络接口数据时曾用到过;小菜对 Stream 的理解还不够深入,基本理解为一个处理器,通过 StreamController()..sink.add() 输入需要处理的数据,通过 StreamController()..stream 输出处理后的数据;整个过程都需要通过 StreamController 来控制;具体的单 stream 和多 stream 方式小菜稍后研究;

2. 绑定数据

  1. StreamProvider({Key key, @required ValueBuilder> builder, T initialData, ..., Widget child })

      通过构建器创建 StreamController 然后绑定数据,注意需要在 initialData 中初始化绑定数据;

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StreamProvider<Teacher>(
        builder: (_) => StreamController<Teacher>(),
        initialData: Teacher('Teacher', 101),
        child: MaterialApp(
            title: 'Flutter Demo',
            theme: ThemeData(primarySwatch: Colors.blue),
            home: MyHomePage(title: 'Peovider Demo')));
  }
}

class Teacher {
  var tname;
  var tage;

  Teacher(this.tname, this.tage);
}

Expanded(child: TextField(
        onChanged: (changed) {
          teacher.tname = changed;
          teacher.tage = 150;
          StreamController<Teacher>().sink.add(teacher);
        },
        controller: _phonecontroller,
        decoration: InputDecoration(
            hintText: '请输入用户名',
            suffixIcon: IconButton(
                icon: Icon(Icons.clear, color: Colors.black45),
                onPressed: () {
                  _phonecontroller.clear();
                }))))
  1. StreamProvider.value({Key key, @required Stream stream, T initialData, ..., Widget child })

      通过 .value 方式对 StreamControllerstream 进行数据绑定,同样需要在 initialData 中初始化数据;

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StreamProvider<Teacher>.value(
        stream: StreamController<Teacher>().stream,
        initialData: Teacher('Teacher', 101),
        child: MaterialApp(
            title: 'Flutter Demo',
            theme: ThemeData(primarySwatch: Colors.blue),
            home: MyHomePage(title: 'Peovider Demo')));
  }
}

3. 获取数据

class ProviderText extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final teacher = Provider.of<Teacher>(context);
    return Center(
        child: Column(children: <Widget>[
      Text('${teacher.tname}'),
      Consumer<Teacher>(builder: (context, teacher, _) {
        return Text('${teacher.tname}==${teacher.tage}');
      })
    ]));
  }
}

小结

  1. 为方便理解,结合上一节的 ChangeNotifierProvider,发现与 ListenableProviderValueListenableProvider 的使用基本相同;
class ChangeNotifierProvider<T extends ChangeNotifier>
    extends ListenableProvider<T> implements SingleChildCloneableWidget {}
class ChangeNotifier implements Listenable {}
    
class ValueListenableProvider<T>
    extends AdaptiveBuilderWidget<ValueListenable<T>, ValueNotifier<T>>
    implements SingleChildCloneableWidget {}
class ValueNotifier<T> extends ChangeNotifier implements ValueListenable<T> {}

      分析源码:ChangeNotifierProvider 继承自 ListenableProvider 且对应的 ChangeNotifier 继承自 listenable;算是 ListenableProvider 的子类;ValueNotifier 继承自 ChangeNotifier 也与 ChangeNotifierProvider 相似;

  1. 使用 ChangeNotifierProviderValueListenableProvider 绑定实体类时需要注意分别继承对应的 ChangeNotifierValueNotifier
class User with ChangeNotifier {}

class Person extends ValueNotifier<User> {}
  1. 无论使用那种 .value 方式,均建议在 dispose 中进行 listener 的关闭;
@override
void dispose() {
    stream.dispose();
    super.dispose();
}

      小菜将 Provier 中提及的五种方式均尝试了一下,对于同一类的实体类也进行测试,如有错误请多多指导!

目录
相关文章
|
26天前
|
存储 JavaScript 前端开发
在Flutter开发中,状态管理至关重要。随着应用复杂度的提升,有效管理状态成为挑战
在Flutter开发中,状态管理至关重要。随着应用复杂度的提升,有效管理状态成为挑战。本文介绍了几种常用的状态管理框架,如Provider和Redux,分析了它们的基本原理、优缺点及适用场景,并提供了选择框架的建议和使用实例,旨在帮助开发者提高开发效率和应用性能。
34 4
|
1月前
|
存储 Shell 开发工具
Flutter&鸿蒙next 中使用 MobX 进行状态管理
本文介绍了如何在 Flutter 中使用 MobX 进行状态管理。MobX 是一个基于观察者模式的响应式编程库,通过 `@observable` 和 `@action` 注解管理状态,并使用 `Observer` 小部件自动更新 UI。文章详细讲解了 MobX 的核心概念、如何集成到 Flutter 项目中以及具体的代码示例。适合希望在 Flutter 应用中实现高效状态管理的开发者阅读。
100 9
|
1月前
|
存储 开发者
Flutter&鸿蒙next 使用 BLoC 模式进行状态管理详解
本文详细介绍了如何在 Flutter 中使用 BLoC 模式进行状态管理。BLoC 模式通过将业务逻辑与 UI 层分离,利用 Streams 和 Sinks 实现状态管理和 UI 更新,提高代码的可维护性和可测试性。文章涵盖了 BLoC 的基本概念、实现步骤及代码示例,包括定义 Event 和 State 类、创建 Bloc 类、提供 Bloc 实例以及通过 BlocBuilder 更新 UI。通过一个简单的计数器应用示例,展示了 BLoC 模式的具体应用和代码实现。
85 1
|
1月前
|
开发工具 开发者
Flutter&鸿蒙next 状态管理高级使用:深入探讨 Provider
本文深入探讨了 Flutter 中 Provider 的高级用法,涵盖多 Provider 组合、Selector 优化性能、ChangeNotifierProxyProvider 管理依赖关系以及自定义 Provider。通过这些技巧,开发者可以构建高效、可维护的响应式应用。
81 2
|
2月前
|
开发工具 开发者
Flutter&鸿蒙next 状态管理高级使用:深入探讨 Provider
Flutter&鸿蒙next 状态管理高级使用:深入探讨 Provider
|
1月前
|
缓存 JavaScript API
Flutter&鸿蒙next 状态管理框架对比分析
在 Flutter 开发中,状态管理至关重要,直接影响应用的性能和可维护性。本文对比分析了常见的状态管理框架,包括 setState()、InheritedWidget、Provider、Riverpod、Bloc 和 GetX,详细介绍了它们的优缺点及适用场景,并提供了 Provider 的示例代码。选择合适的状态管理框架需考虑应用复杂度、团队熟悉程度和性能要求。
109 0
|
2月前
【Flutter】状态管理:Provider状态管理
【Flutter】状态管理:Provider状态管理
24 0
|
2月前
|
UED
flutter:动画&状态管理 (十三)
本文档介绍了Flutter中`animatedList`的使用方法和状态管理的示例。`animatedList`用于创建带有动画效果的列表,示例代码展示了如何添加、删除列表项,并执行相应的动画效果。状态管理部分通过一个简单的点击切换颜色的示例,演示了如何在Flutter中管理组件的状态。
|
5月前
|
容器
flutter 布局管理【详解】
flutter 布局管理【详解】
45 3
|
4月前
Flutter 状态管理新境界:多Provider并行驱动UI
Flutter 状态管理新境界:多Provider并行驱动UI
81 0