首页 > 解决方案 > 使用 Scoped Model 在 Flutter 中维护应用程序状态

问题描述

我需要帮助为我的应用程序创建架构。我正在使用 Flutter 和scoped_model来维护状态。

这是一个具有登录功能的应用程序,在应用程序的一部分中显示新闻,并显示照片库等。我想将整个事情分成单独的模型。保存登录状态(如用户名、令牌、名称等)的 LoginModel。包含从 API 检索到的新闻的 NewsModel。GalleryModel 保存照片名称等。我不确定这是否是使用 scoped_model 维护状态的最佳实践。

例如,如果文本框同时依赖于 LoginModel 和 NewsModel,该怎么办?我不确定,但我想不可能从两个单独的模型中检索状态。此外,我维护单独的模型以保持状态的主要原因是我不希望应用程序的登录部分在我带来新闻时被刷新。我想当我将整个状态放在一个模型中时,情况就是这样。

标签: flutterscoped-model

解决方案


scoped_model库旨在同时使用多个模型。这就是ScopedModelandScopedModelDescendant是泛型并具有类型参数的部分原因。您可以使用 Widget 树的顶部附近定义多个模型,然后使用ScopedModel<LoginModel>和在树的较低位置使用这些模型。后代将根据他们的类型参数去寻找合适的模型。ScopedModel<NewsModel>ScopedModelDescendant<LoginModel>ScopedModelDescendant<NewsModel>

我拼凑了一个简单的例子。以下是模型:

class ModelA extends Model {
  int count = 1;
  void inc() {
    count++;
    notifyListeners();
  }
}

class ModelB extends Model {
  int count = 1;
  void inc() {
    count++;
    notifyListeners();
  }
}

这是我在应用程序中显示的内容:

ScopedModel<ModelA>(
  model: ModelA(),
  child: ScopedModel<ModelB>(
    model: ModelB(),
    child: ScopedModelDescendant<ModelA>(
      builder: (_, __, a) => ScopedModelDescendant<ModelB>(
        builder: (_, __, b) {
          return Center(
            child: Column(
              children: [
                GestureDetector(
                  onTap: () => a.inc(),
                  child: Text(a.count.toString()),
                ),
                SizedBox(height:100.0),
                GestureDetector(
                  onTap: () => b.inc(),
                  child: Text(b.count.toString()),
                ),
              ],
            ),
          );
        },
      ),
    ),
  ),
)

它似乎工作得很好。非嵌套方法也适用:

ScopedModel<ModelA>(
  model: ModelA(),
  child: ScopedModel<ModelB>(
    model: ModelB(),
    child: Column(
      children: [
        ScopedModelDescendant<ModelA>(
          builder: (_, __, model) => GestureDetector(
                onTap: () => model.inc(),
                child: Text(model.count.toString()),
              ),
        ),
        SizedBox(height: 100.0),
        ScopedModelDescendant<ModelB>(
          builder: (_, __, model) => GestureDetector(
                onTap: () => model.inc(),
                child: Text(model.count.toString()),
              ),
        ),
      ],
    ),
  ),
)

推荐阅读