Flutter状态管理插件scoped_model的使用

发布于 1周前 作者 ionicwang 来自 Flutter

Flutter状态管理插件scoped_model的使用

Scoped Model 是一个Flutter的状态管理库,它提供了一组工具,使你可以轻松地将数据模型从父Widget传递到其子Widget。当模型更新时,它还会重建所有使用该模型的子组件。此库最初是从Fuchsia代码库中提取出来的。

主要特性

Scoped Model 库提供了三个主要类:

  • Model 类:你需要扩展此类来创建自己的模型,如 SearchModelUserModel。你可以监听这些模型的变化。
  • ScopedModel Widget:如果你需要将一个 Model 深层传递到你的Widget树中,你可以将你的 Model 包装在一个 ScopedModel Widget中。这会使模型对所有后代Widget可用。
  • ScopedModelDescendant Widget:使用此Widget可以在Widget树中找到合适的 ScopedModel。每当模型通知发生变化时,它会自动重建。

使用示例

接下来我们将通过一个简单的计数器应用来演示如何使用 Scoped Model。

定义模型

首先,我们需要定义一个包含应用程序状态的类。在这个例子中,我们创建了一个简单的计数器,它从0开始并可以递增。

class CounterModel extends Model {
  int _counter = 0;

  int get counter => _counter;

  void increment() {
    // 先递增计数器
    _counter++;
    
    // 然后通知所有的监听者
    notifyListeners();
  }
}

创建应用

然后,我们创建应用,并在顶层使用 ScopedModelCounterModel 提供给所有需要它的子组件。

void main() {
  runApp(MyApp(
    model: CounterModel(),
  ));
}

class MyApp extends StatelessWidget {
  final CounterModel model;

  const MyApp({Key? key, required this.model}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ScopedModel<CounterModel>(
      model: model,
      child: MaterialApp(
        title: 'Scoped Model Demo',
        home: CounterHome('Scoped Model Demo'),
      ),
    );
  }
}

使用模型

最后,在具体的页面或组件中使用 ScopedModelDescendant 来获取和操作 CounterModel

class CounterHome extends StatelessWidget {
  final String title;

  CounterHome(this.title);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('You have pushed the button this many times:'),
            // 获取 CounterModel 并显示计数器值
            ScopedModelDescendant<CounterModel>(
              builder: (context, child, model) {
                return Text(
                  model.counter.toString(),
                  style: Theme.of(context).textTheme.headline4,
                );
              },
            ),
          ],
        ),
      ),
      // 使用 CounterModel 的 increment 方法
      floatingActionButton: ScopedModelDescendant<CounterModel>(
        builder: (context, child, model) {
          return FloatingActionButton(
            onPressed: model.increment,
            tooltip: 'Increment',
            child: Icon(Icons.add),
          );
        },
      ),
    );
  }
}

这个例子展示了如何使用 ScopedModelScopedModelDescendant 来管理Flutter应用中的状态。通过这种方式,我们可以保持UI与业务逻辑分离,并且确保只有依赖于特定模型的部分才会被重新构建,提高了性能。

找到模型

有两种方式可以找到由 ScopedModel 提供的模型:

  1. 使用 ScopedModelDescendant Widget。它会在模型变化时(即调用了 notifyListeners)触发构建函数。
  2. 使用 ScopedModel.of 静态方法直接获取模型。为了提高可读性,你可以在自己的模型类中添加自定义的 of 方法。

例如:

class CounterModel extends Model {
  // ...
 
  /// 包装 [ScopedModel.of] 用于此 [Model].
  static CounterModel of(BuildContext context) =>
      ScopedModel.of<CounterModel>(context);
}

监听多个模型

如果需要在一个构建函数中监听多个模型的数据,可以通过以下两种方式实现:

  1. 使用多个 ScopedModelDescendant Widgets。
  2. 使用多次 ScopedModel.of 调用。无需管理订阅关系,因为Flutter通过 InheritedWidgets 的魔力处理了这一切。

例如:

class CombinedWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final username =
      ScopedModel.of<UserModel>(context, rebuildOnChange: true).username;
    final counter =
      ScopedModel.of<CounterModel>(context, rebuildOnChange: true).counter;

    return Text('$username tapped the button $counter times');
  }
}

这就是关于 scoped_model 插件的基本介绍和使用方法。希望这对您有所帮助!


更多关于Flutter状态管理插件scoped_model的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter状态管理插件scoped_model的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter中使用scoped_model插件进行状态管理的示例。请注意,scoped_model插件在较新的Flutter版本中可能已经被其他更现代的状态管理解决方案(如Provider、Riverpod等)所取代,但了解它的工作原理仍然对理解状态管理的基础有帮助。

首先,确保你的pubspec.yaml文件中包含了scoped_model依赖:

dependencies:
  flutter:
    sdk: flutter
  scoped_model: ^1.1.0  # 请检查最新版本号

然后,运行flutter pub get来安装依赖。

接下来,我们将创建一个简单的Flutter应用,使用scoped_model来管理应用的状态。

1. 创建Model

首先,我们需要创建一个Model类,它继承自Model类,并提供一些数据和修改数据的方法。

import 'package:scoped_model/scoped_model.dart';

class CounterModel extends Model {
  int _counter = 0;

  int get counter => _counter;

  void increment() {
    _counter++;
    notifyListeners();  // 通知监听器数据已更改
  }
}

2. 创建UI组件

然后,我们创建一个使用ScopedModel的UI组件。

import 'package:flutter/material.dart';
import 'package:scoped_model/scoped_model.dart';
import 'counter_model.dart';  // 假设你将Model类保存在这个文件中

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ScopedModel<CounterModel>(
      model: CounterModel(),  // 初始化Model
      child: MaterialApp(
        home: ScopedModelDescendant<CounterModel>(
          builder: (context, child, model) {
            return Scaffold(
              appBar: AppBar(
                title: Text('Scoped Model Demo'),
              ),
              body: Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Text(
                      'You have pushed the button this many times:',
                    ),
                    Text(
                      '${model.counter}',
                      style: Theme.of(context).textTheme.headline4,
                    ),
                  ],
                ),
              ),
              floatingActionButton: FloatingActionButton(
                onPressed: model.increment,
                tooltip: 'Increment',
                child: Icon(Icons.add),
              ),
            );
          },
        ),
      ),
    );
  }
}

3. 运行应用

将上述代码保存为相应的Dart文件(如main.dart),然后运行你的Flutter应用。你应该会看到一个简单的界面,上面有一个按钮和一个显示计数器值的文本。每次点击按钮时,计数器值都会增加。

注意事项

  • ScopedModel是一个较老的状态管理库,对于新项目,建议使用更现代的解决方案,如Provider或Riverpod。
  • 在使用ScopedModel时,确保你已经正确安装并导入了所需的依赖。
  • notifyListeners()方法在数据更改时调用,以通知所有监听该模型的组件刷新UI。

这个示例展示了如何使用scoped_model插件在Flutter中进行基本的状态管理。希望这对你有所帮助!

回到顶部