什么是Scoped_model
Scoped_model是一个dart第三方库,提供了让您能够轻松地将数据模型从父Widget传递到它的后代的功能。此外,它还会在模型更新时重新渲染使用该模型的所有子项。
它直接来自于Google正在开发的新系统Fuchsia核心Widgets 中对Model类的简单提取,作为独立使用的独立Flutter插件发布。
实现原理
Scoped model使用了观察者模式,将数据模型放在父代,后代通过找到父代的model进行数据渲染,最后数据改变时将数据传回,父代再通知所有用到了该model的子代去更新状态。
而我们则需要将它们放在顶层入口MaterialApp之上,这样就能进行全局的状态管理了。
这里page3,page4代表使用到该状态(model)的子页面。
import 'package:flutter/material.dart'; import 'package:scoped_model/scoped_model.dart'; class StateModelDemo extends StatelessWidget { @override Widget build(BuildContext context) { // TODO: implement build return ScopedModel( model:CounteModel(), child: Scaffold( appBar: AppBar( title: Text('状态管理'), ), body: CountWrap(), //使用Model中的方法 floatingActionButton:ScopedModelDescendant<CounteModel>( //当前的小部件是否重建 rebuildOnChange: false, builder: (context,_,model)=> FloatingActionButton( child: Icon(Icons.add), onPressed: model.addCount, ), ), ), ); } } class CountWrap extends StatelessWidget { @override Widget build(BuildContext context) { // TODO: implement build return Container( child: CountData(), ); } } class CountData extends StatelessWidget { @override Widget build(BuildContext context) { return ScopedModelDescendant<CounteModel>( builder: (context,_,model)=>Center( child: ActionChip( label: Text('${model.count}'), onPressed: model.addCount, ), ), ); } } class CounteModel extends Model { //定义需要传递的数据 int _count = 0; //获取传递的数据 int get count => _count; //需要执行的函数 void addCount() { _count+=1; //重构部件,使用Model的小部件会监听Model的变化,使用了notifyListeners方法,这些监听的小部件就会被重建 notifyListeners(); } }
第一步:创建Model
class CounteModel extends Model { //定义需要传递的数据 int _count = 0; //获取传递的数据 int get count => _count; //需要执行的函数 void addCount() { _count+=1; //重构部件,使用Model的小部件会监听Model的变化,使用了notifyListeners方法,这些监听的小部件就会被重建 notifyListeners(); } }
第二步:将Model放入顶层
class StateModelDemo extends StatelessWidget { @override Widget build(BuildContext context) { // TODO: implement build return ScopedModel( model:CounteModel(), child: Scaffold( appBar: AppBar( title: Text('状态管理'), ), body: CountWrap(), //使用Model中的方法 floatingActionButton:ScopedModelDescendant<CounteModel>( //当前的小部件是否重建 rebuildOnChange: false, builder: (context,_,model)=> FloatingActionButton( child: Icon(Icons.add), onPressed: model.addCount, ), ), ), ); } }
我们在顶层创建了一个CounteModel的实例。
ScopedModel<T extends Model>是一个StatelessWidget,它接收一个model,并提供给需要它的所有部件。
将ScopedModel<T extends Model>的model属性绑定我们的CounteModel对象。
第三步:在子页面中获取Model
Scoped_model提供了两种方式在子页面中获取model。我们先来介绍第一种,使用ScopedModelDescendant获取model。
class CountData extends StatelessWidget { @override Widget build(BuildContext context) { return ScopedModelDescendant<CounteModel>( builder: (context,_,model)=>Center( child: ActionChip( label: Text('${model.count}'), onPressed: model.addCount, ), ), ); } }
ScopedModelDescendant<T extends Model>是一个Stateless Widget,它接收三个参数。
ScopedModelDescendant({ @required this.builder, this.child, this.rebuildOnChange = true,//当前部件是否需要重构 });
builder是一个ScopedModelDescendantBuilder<T>,它接收三个参数。
Widget build(BuildContext context) { return builder( context,//上下文对象 child,//子部件 ScopedModel.of<T>(context, rebuildOnChange: rebuildOnChange), ); }
rebuildOnChange属性能够控制当该状态发生变化时,是否rebuild,作用等同于setState。也就是说我们调用改变状态的一些方法时,不必再setState。
第二种获取model的方式——使用ScopedModel.of
final countModel = ScopedModel.of<CountModel>(context); countModel.increment();
或者在Model中重写of方法
class CountModel extends Model{ int _count = 0; get count => _count; void increment(){ _count++; notifyListeners(); }//重写of方法 CountModel of(context) => ScopedModel.of<CountModel>(context); }
然后直接通过CountModel获取model实例
final countModel2 = CountModel().of(context);
发表评论
侧栏公告
寄语
譬如朝露博客是一个分享前端知识的网站,联系方式11523518。
热评文章
标签列表
热门文章
友情链接