当前位置: 首页 > news >正文

Flutter_学习记录_数据更新的学习

Flutter 如果界面上有数据更新时,目前学习到的有3种:

  • 第一种: 直接用 StatefulWidget组件,然后当数据更新时,调用setState的方法更新数据,页面上的数据会直接更新;
  • 第二种: 用 StatefulWidget组件 和 InheritedWidget 的结合,这种模式比较适用于有比较多层级的场景;这样数据更新时,就不用一层一层的从父类上传递数据;
  • 第三种:用第三方库scoped_model, 这种模式下在StatelessWidget也可以实现UI页面上数据的更新。

如要实现下面这个页面的效果(点击 count:x 和底部"+", 实现count的数据加1):
在这里插入图片描述

1. StatefulWidget 更新数据的使用

这个比较简单,代码如下:

import 'package:flutter/material.dart';

class StatemanagerDemo extends StatefulWidget {
  const StatemanagerDemo({super.key});

  
  State<StatemanagerDemo> createState() => _StatemanagerDemoState();
}

class _StatemanagerDemoState extends State<StatemanagerDemo> {
  int _count = 0;

  void _increaseCount() {
  	// 这个是关键,只有调用 setState 才能更新页面的数据
    setState(() {
      _count += 1;
    });
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("StateManagerDemo"),
      ),
      body: CounterWidget(count: _count, increaseCount: _increaseCount),
      floatingActionButton:  FloatingActionButton(
        onPressed: _increaseCount,
        child: Icon(Icons.add),
      ),
    );
  }
}

class CounterWidget extends StatelessWidget {
  final int count;
  final VoidCallback increaseCount;

  const CounterWidget({super.key, required this.count, required this.increaseCount});

  
  Widget build(BuildContext context) {
    return Center(
      child: ActionChip(
        label: Text("$count"),
        onPressed: increaseCount
      )
    );
  }
}

2. StatefulWidget组件 和 InheritedWidget 的结合

代码如下:

//-------用InheritedWidget 实现数据的更新------
class StateManagerInheriteDemo extends StatefulWidget {
  const StateManagerInheriteDemo({super.key});

  
  State<StateManagerInheriteDemo> createState() => _StateManagerInheriteDemoState();
}

class _StateManagerInheriteDemoState extends State<StateManagerInheriteDemo> {
  int _count = 0;

  void _increaseCount() {
    setState(() {
      _count += 1;
    });
  }

  
  Widget build(BuildContext context) {
    return CounterProvider(
      count: _count, 
      increaseCount: _increaseCount, 
      child: Scaffold(
        appBar: AppBar(
          title: Text("StateManagerDemo"),
        ),
        body: CounterWidgetInherite(),
        floatingActionButton:  FloatingActionButton(
          onPressed: _increaseCount,
          child: Icon(Icons.add),
        ),
      )
    );
    
  }
}

// 创建一个provider类来提供全局可用的数据存储和获取
class CounterProvider extends InheritedWidget {
  final int count;
  final VoidCallback increaseCount;
  final Widget child;

  const CounterProvider({super.key, required this.count, required this.increaseCount, required this.child}) : super(child: child);
 
  // 定义一个of方法,可以获取CounterProvider的数据
  static CounterProvider? of(BuildContext context) => context.dependOnInheritedWidgetOfExactType<CounterProvider>();

  
  bool updateShouldNotify(covariant InheritedWidget oldWidget) {
    return true;
  }
}

// 模拟多个层级1
class CounterWidgetInherite extends StatelessWidget {
  const CounterWidgetInherite ({super.key});

  
  Widget build(BuildContext context) {
    return Center(
      child: Counter(),
    );
  }
}

// 模拟多个层级2
class Counter extends StatelessWidget {
  const Counter({super.key});

  
  Widget build(BuildContext context) {
    final int? count = CounterProvider.of(context)?.count;
    final VoidCallback? increaseCount = CounterProvider.of(context)?.increaseCount;
    
    return ActionChip(
      label: Text("$count"),
      onPressed: increaseCount,
    );
  }
}

3. scoped_model 的使用

scoped_model 是第三方库,需要在项目中引入三方库(引入三方库的方法,参考这个文章);其次,该模式引用到的组件主要是:

  • ScopedModel
  • ScopedModelDescendant

原理还没搞明白,只是看着视频实现了功能,代码如下:

import 'package:flutter/material.dart';
import 'package:scoped_model/scoped_model.dart';

//-------用Scoped_Model 实现数据的更新-----
class StateManagerScopteModelDemo extends StatelessWidget {
  const StateManagerScopteModelDemo({super.key});

  
  Widget build(BuildContext context) {
    // 用ScopedModel 包装一下,提供model属性对应的类型
    return ScopedModel(
      model: CounterModel(), 
      child: Scaffold(
        appBar: AppBar(
          title: Text("StateManagerDemo"),
        ),
        body: CounterWidgetScopteModel(),
        // ScopedModelDescendant 的构建方法获取CounterModel对应的数据
        floatingActionButton:  ScopedModelDescendant<CounterModel>(
          rebuildOnChange: false,
          builder: (context, _, model) {
            return FloatingActionButton(
              onPressed: model.increaseCount,
              child: Icon(Icons.add),
            );
          }
        ),
      )
    );
  }
}

class CounterWidgetScopteModel extends StatelessWidget {
  const CounterWidgetScopteModel ({super.key});

  
  Widget build(BuildContext context) {
    return Center(
      // ScopedModelDescendant 的构建方法获取CounterModel对应的数据
      child: ScopedModelDescendant<CounterModel>(
        builder: (context, _, model) {
          return ActionChip(
              label: Text("count: ${model.count}"),
              onPressed: model.increaseCount,
          );
        }
      ),
    );
  }
}

// 创建继承于Model的业务类,来存放对应的count和用到的方法
class CounterModel extends Model {
  int _count = 0;
  int get count => _count;

  void increaseCount() {
    _count += 1;
    // 使用Model小部件的地方会监听Model的变化,可以用notifyListeners方法重建UI 
    notifyListeners();
  }
}

相关文章:

  • call、apply、bind 详解
  • Windows 图形显示驱动开发-WDDM的优势和迁移
  • 03-微服务01(服务拆分、RestTemplate,nacos、OpenFeign、日志)
  • 区块链中的数字签名:安全性与可信度的核心
  • 小程序之间实现互相跳转的逻辑
  • 详解Cookie和Session
  • DeepseeK自动写作,自动将回答导出文档
  • 小米 R3G 路由器(Pandavan)实现网络打印机功能
  • LINUX常用命令学习
  • vue开发06:前端通过webpack配置代理处理跨域问题
  • Linux 共享内存
  • Python教程108:针对面向对象Class类知识要点,源码示例再演示
  • Qt的QTreeWidge的使用
  • 从技术债务到架构升级,滴滴国际化外卖的变革
  • MySQL错误-this is incompatible with sql_mode=only_full_group_by完美解决方案
  • 大模型的未来已来
  • 苍穹外卖学习
  • 谭浩强C语言程序设计(5) 9章
  • 通俗理解-L、-rpath和-rpath-link编译链接动态库
  • pyqt自制简单浏览器(python)
  • flash网站建设/seo网站排名软件
  • 网站的三大标签/长春网站优化流程
  • 网站关键字个数/广州网站设计制作
  • 沈阳世纪兴网站建设/网站排名优化教程
  • 北京著名网站建设公司/昆明装饰企业网络推广
  • 网站备案在哪个网/网站优化seo培