首页 > 其他分享 >Provider 四种消费者

Provider 四种消费者

时间:2023-12-30 15:23:24浏览次数:38  
标签:Widget 消费者 Text Provider BuildContext context child 四种

Provider.of

Provider.of 方法是 Provider 库中最常用的获取共享数据的方法之一。它接收一个 BuildContext 对象和一个泛型类型参数 T,会查找 Widget 树中最近的一个类型为 T 的 Provider 对象,并返回它所提供的共享数据。当共享数据发生变化时,它会自动重新构建与该共享数据有依赖关系的 StatefulWidget。

模型
class UserModel with ChangeNotifier {

  String name = "Jimi";
  int aa = 0;

  void changeName() {
    aa++;
    name = "hello"+aa.toString();
    print(name);
    notifyListeners();
  }
}
入口设置
class MyApp9 extends StatelessWidget {
  const MyApp9({super.key});

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<UserModel>(
      create: (_) =>UserModel(),
      child:  MaterialApp(
        debugShowCheckedModeBanner: false,
        home: Example(),
      ),
      
      );
  }
}
使用
class Example extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("ConsumerExample"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              Provider.of<UserModel>(context).name,
              style: const TextStyle(color: Colors.red, fontSize: 50),
            ),
            Padding(
              padding: EdgeInsets.only(top: 20),
              child: ElevatedButton(
                onPressed: () {
                  Provider.of<UserModel>(context, listen: false)
                      .changeName(); //listen: false 必加
                },
                child: Text("点击加1"),
              ),
            )
          ],
        ),
      ),
    );
  }
}

*Consumer

 Consumer 是一个轻量级的组件,用于消费共享数据并构建 UI。它接收一个 BuildContext 对象和一个 builder 函数作为参数,在 builder 函数中构建 UI,该 UI 依赖于共享数据。当共享数据发生变化时,Consumer 会自动重新构建 UI。

里面有三个属性:

  • context: 当前的上下文
  • **Provider.of(context):** 模型对象
  • child: 子组件(不需要刷新的部分)
模型
  String name = "Jimi";
  int aa = 0;

  void changeName() {
    aa++;
    name = "hello$aa";
    print(name);
    notifyListeners();
  }
}
入口设置
class MyApp9 extends StatelessWidget {
  const MyApp9({super.key});

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<UserModel>(
      create: (_) =>UserModel(),
      child:  MaterialApp(
        debugShowCheckedModeBanner: false,
        home: Example(),
      ),
      );
  }
}
使用
class Example extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("ConsumerExample"),
      ),
      body: Consumer<UserModel>(
        builder: (_, UserModel userModel, child) {
          return Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text(
                  userModel.name.toString(),
                  style: const TextStyle(color: Colors.red, fontSize: 50),
                ),
                Padding(
                  padding: const EdgeInsets.only(top: 20),
                  child: ElevatedButton(
                    onPressed: () {
                      userModel.changeName();
                    },
                    child: const Text("点击加1"),
                  ),
                ),
                Container(
                  //每次都需要加载
                  child: const Column(
                    children: [
                      Text("更多组件1"),
                      Text("更多组件2"),
                      Text("更多组件3"),
                      Text("更多组件4"),
                      Text("更多组件5"),
                      Text("更多组件6"),
                    ],
                  ),
                ),
                child! //可选参数 1.不用每次都加载
              ],
            ),
          );
        },
        child: const Column(
          //2.不用每次都加载
          children: [
            Text("1更多组件1"),
            Text("1更多组件2"),
            Text("1更多组件3"),
            Text("1更多组件4"),
            Text("1更多组件5"),
          ],
        ),
      ),
    );
  }
}

Selector

Selector类和Consumer类似,只是对build调用Widget方法时提供更精细的控制,简单点来说,Selector也是一个消费者,它允许你可以从模型中准备定义哪些属性;Selector 是一个高级的组件,也用于消费共享数据并构建 UI。它接收一个 BuildContext 对象、一个 selector 函数和一个 builder 函数作为参数。selector 函数用于选择需要依赖的共享数据,当且仅当 selector 函数返回的数据发生变化时,Selector 才会重新构建 UI。这可以有效地避免不必要的重建,提高性能。

比如,用户模型中有50个属性,但是我只需要更新年龄,这样我希望不需要重建用户名、电话号码等组件;

模型
class UserModel6 with ChangeNotifier {

  String name = "Jimi";
  int age = 18;
  String phone = "18888888888";


  void increaseAge() {
    age++;
    notifyListeners(); //通知注册的监听器
  }
}
入口设置
class MyApp9 extends StatelessWidget {
  const MyApp9({super.key});

  @override
  Widget build(BuildContext context) {
return ChangeNotifierProvider(
  create: (_) => UserModel6(),
  child: MaterialApp(
    debugShowCheckedModeBanner: false,
    home: SelectorExample(),
  ),
);
  }
}
使用
class SelectorExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("SelectorExample"),
      ),
      body: Center(
        child: Selector<UserModel6, int>(
          selector: (_, userModel6) => userModel6.age,
          builder: (_, age, child) {
            return Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text(age.toString(),
                    style: const TextStyle(color: Colors.red, fontSize: 30)),
                child!
              ],
            );
          },
          child: Padding(
            padding: EdgeInsets.all(20),
            child: ElevatedButton(
              onPressed: () {
                Provider.of<UserModel6>(context, listen: false).increaseAge();
              },
              child: Text("改变年龄"),
            ),
          ),
        ),
      ),
    );
  }
}

InheritedContext

InheritedContext 是 Provider 内部使用的一个类,用于在 Widget 树中传递共享数据的上下文。在 Provider 中,它被优化为一个轻量级的实现。通常情况下,我们不需要直接使用 InheritedContext。

三大方式:

BuildContext.read:

 BuildContext.read<CountNotifier1>()可以替换掉Provider.of<CountNotifier1>(context,listen: false),它会找到CountNotifier1并返回它。

class InheritedContextExample extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("InheritedContextExample"),
      ),
      /// read 获取值
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(context.read<CountNotifier2>().count.toString(),
              style: TextStyle(
                  color: Colors.red,
                  fontSize: 50
              ),
            ),
            Padding(
              padding: EdgeInsets.only(top: 20),
              child: ElevatedButton(
                onPressed: () => Provider.of<CountNotifier2>(context, listen: false).increment(),
                child: Text("点击加1"),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
BuildContext.watch:

 BuildContext.watch<CountNotifier1>()可以替换掉Provider.of<CountNotifier1>(context,listen: false),看起来和read没有什么不同,但是使用watch你就不需要在使用Consumer

class InheritedContextExample extends StatelessWidget {

  @override
  Widget build(BuildContext context) {

         /// 重要(必须)
    final countNotifier2 = context.watch<CountNotifier2>();  

    return Scaffold(
      appBar: AppBar(
        title: Text("InheritedContextExample"),
      ),
      /// watch 
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(countNotifier2.count.toString(),
              style: TextStyle(
                  color: Colors.red,
                  fontSize: 50
              ),
            ),
            Padding(
              padding: EdgeInsets.only(top: 20),
              child: ElevatedButton(
                onPressed: () => countNotifier2.increment(),
                child: Text("点击加1"),
              ),
            ),
          ],
        ),
      ),

    );
  }
}
BuildContext.select:

 BuildContext.select<CountNotifier1>()可以替换掉Provider.of<CountNotifier1>(context,listen: false),看起来和watch也没有什么不同,但是使用select你就不需要在使用Selector

class InheritedContextExample extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    
    /// 重要
    final count = context.select((CountNotifier2 countNotifier2) => countNotifier2.count);

    return Scaffold(
      appBar: AppBar(
        title: Text("InheritedContextExample"),
      ),
      /// select
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(count.toString(),
              style: TextStyle(
                  color: Colors.red,
                  fontSize: 50
              ),
            ),
            Padding(
              padding: EdgeInsets.only(top: 20),
              child: ElevatedButton(
                onPressed: () => Provider.of<CountNotifier2>(context, listen: false).increment(),
                child: Text("点击加1"),
              ),
            )
          ],
        ),
      ),
    );
  }
}

 

参考于 Flutter Provider状态管理---四种消费者使用分析 | Jimi (liujunmin.com)

 

标签:Widget,消费者,Text,Provider,BuildContext,context,child,四种
From: https://www.cnblogs.com/xbinbin/p/17936142.html

相关文章

  • Provider的八种提供者
    代码classExampleextendsStatelessWidget{@overrideWidgetbuild(BuildContextcontext){returnScaffold(appBar:AppBar(title:constText("Example"),),body:Center(child:Column(mainAxi......
  • 【专题】2023年中国消费者洞察白皮书报告PDF合集分享(附原数据表)
    全文链接:https://tecdat.cn/?p=33375原文出处:拓端数据部落公众号在疫情后的时代,中国的消费市场正在逐步复苏。政策和社会共同努力,全面提振消费者的信心。与此同时,供给侧正在采用新的内容营销模式,品牌、电商直播和信息平台注重科普专业知识,将品质和创新作为核心竞争力。居民消费......
  • 深入探究多线程中的虚假唤醒现象--从生产者消费者问题到高级解决方案的全方位解读
    文章目录生产者和消费者问题虚假呼唤问题解决方案线程之间的虚假唤醒问题常出现在多线程编程中。我看国内很多教程都解释的稀里糊涂的,所以打算写一篇博客好好絮叨絮叨。首先看一下线程虚假唤醒的定义:多线程环境下,有多个线程执行了wait()方法,需要其他线程执行notify()或者notifyAl......
  • Kafka 再均衡详解:实现消费者组的负载均衡和故障转移(十二)
    在Kafka中,再均衡(Rebalancing)是指在消费者组内部发生变化时,Kafka会重新分配分区给消费者,以实现负载均衡和故障转移的目的。再均衡是Kafka实现高可用性和可扩展性的重要机制之一。再均衡的场景消费者加入、消费者退出和分区变化等情况。消费者加入:当新的消费者加入消费者组......
  • MySQL查询慢,四种方案帮你解决!
    一般分页在系统中需要进行分页操作时,我们通常会使用LIMIT加上偏移量的方式实现,语法格式如下。SELECT...FROM...WHERE...ORDERBY...LIMIT...在有对应索引的情况下,这种方式一般效率还不错。但它存在一个让人头疼的问题,在偏移量非常大的时候,也就是翻页到很靠后的页面......
  • 安卓之DocumentsProvider应用场景以及优劣分析
    文章摘要本文深入探讨了安卓DocumentsProvider的应用场景,分析了其优势与不足,并提供了简单的代码实现。DocumentsProvider是安卓系统中用于文件存储与访问的关键组件,为应用开发者提供了强大的文件管理能力。正文DocumentsProvider概述DocumentsProvider是安卓系统中的一个组件,允许应......
  • 安卓之DocumentsProvider应用场景以及优劣分析
    文章摘要本文深入探讨了安卓DocumentsProvider的应用场景,分析了其优势与不足,并提供了简单的代码实现。DocumentsProvider是安卓系统中用于文件存储与访问的关键组件,为应用开发者提供了强大的文件管理能力。正文DocumentsProvider概述DocumentsProvider是安卓系统中的......
  • 查看NVIDIA CUDA版本号的四种方法
    查看CUDA版本号这里有三种方法。nvidia-smi运行nvidia-smi命令:右上角可以看到CUDA版本号。CUDAToolkit下载地址:https://developer.nvidia.com/cuda-downloads$nvcc-Vnvcc:NVIDIA(R)CudacompilerdriverCopyright(c)2005-2023NVIDIACorporationBuiltonFri_Nov__3_17......
  • C# 读写 Excel 四种方案(OpenXml、NPOI、EPPlus、Spire.Office)
    C#读写Excel四种方案(OpenXml、NPOI、EPPlus、Spire.Office)翔星有10年+工作经验,高级软件工程师,可以解决各种问题​关注 你经常看TA的内容前言在项目中需要使用C#读写Excel,每天定时将数据输出到Excel表格中。在参考了很多的方案后,找到了4......
  • 简述四种线上环境建设思路
    转载于:https://blog.csdn.net/key_3_feng/article/details/129759225内容来源于极客时间《赵成的运维体系管理课》  由线下正式交付到线上之前,我们仍然会做很多的验证和稳定性保障工作。就生产环境、灰度环境、预发环境、办公网生产环境这四种线上环境的建设进行分析。1......