首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在连接器(ScopedModel)中连接多个模型

如何在连接器(ScopedModel)中连接多个模型
EN

Stack Overflow用户
提问于 2020-02-24 17:15:50
回答 1查看 475关注 0票数 1

我试图把水果添加到购物车中,但是没有发生任何事情,

一旦我按下‘添加水果’按钮,什么都不会发生。它假设在购物车列表中添加水果项目。有一次,在按下“添加水果”按钮后,我在应用程序栏中按下购物车图标,试图访问购物车屏幕时出错。

以这种方式不能正常工作:

代码语言:javascript
复制
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new ScopedModel(
      model: ListModel(),
      child: ScopedModel(
        model: CartModel(),
        child: MaterialApp(
          debugShowCheckedModeBanner: false,
          title: 'State Management Scoped Model',
          theme: myAppTheme,
          initialRoute: '/',
          routes: {
            '/': (context) => MyList(),
            '/cart': (context) => MyCart(),
          },
        ),
      ),
    );
  }
}

也是另一种方式:

代码语言:javascript
复制
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new ScopedModel<ListModel>(
      model: ListModel(),
      child: ScopedModelDescendant<ListModel>(
        builder: (context, child, model) => ScopedModel<CartModel>(
          model: CartModel(),
        ),
        child: MaterialApp(
          debugShowCheckedModeBanner: false,
          title: 'State Management Scoped Model',
          theme: myAppTheme,
          initialRoute: '/',
          routes: {
            '/': (context) => MyList(),
            '/cart': (context) => MyCart(),
          },
        ),
      ),
    );
  }
}

对于提供者包,一切都很好:)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-02-24 20:17:17

还不能发表评论。

当对模型的更改实际影响UI时,尝试将MaterialApp添加为ScopedModel的直接子代,并使用ScopedModelDescendant。

代码语言:javascript
复制
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new ScopedModel<ListModel>(
      model: ListModel(),
      child: MaterialApp(
         debugShowCheckedModeBanner: false,
         title: 'State Management Scoped Model',
         theme: myAppTheme,
         initialRoute: '/',
         routes: {
           '/': (context) => MyList(),
           '/cart': (context) => MyCart(),
         },
       ),
    );
  }
}

当属性发生变化时,当您列出卡片项时,可以在MyCart小部件中表示

代码语言:javascript
复制
... widget tree ...

child: ScopedModelDescendant<ListModel>(
         builder: (context, child, ScopedModel<CartModel> model){
           List cartItems = model.cartItems;
           List<Widget> cartItemWidgets=[];
           cartItems.forEach((cartItemData){
             cartItemWidgets.add(new CartItemWidget(cartItemData));
           });
           return Column(
             children:cartItemWidgets,
           );
         }
       ),

...widget tree...

希望这能有所帮助。

注意,每次调用ScopedModelDescendant ()时,notifyLsteners都会发生变化。我认为,在整个应用程序上这么做是非常昂贵的。

编辑:

忘记添加rebuildOnChange: true属性。也犯了个错误。

代码语言:javascript
复制
... widget tree ...
//__YOUR__MODEL__: model that changes 
child: ScopedModelDescendant<__YOUR__MODEL__>(
         rebuildOnChange: true, // now the widget rebuilds when notifyListeners(); is called inside the __YOUR__MODEL__
         builder: (context, child,__YOUR__MODEL__ model){
           List cartItems = model.cartItems;
           List<Widget> cartItemWidgets=[];
           cartItems.forEach((cartItemData){
             cartItemWidgets.add(new CartItemWidget(cartItemData));
           });
           return Column(
             children:cartItemWidgets,
           );
         }
       ),

...widget tree...

编辑2:

通过查看git存储库,我能够构建一个示例来说明您想要做的事情。这是链接到GitHub存储库。注意:我已经启动了对你的所有权转让。如果你愿意的话我会更新链接。但也要描述一下实现。

您希望有两个模型-- ListModel和CartModel,列表模型目前用作实际列表的占位符。

在CartModel中,您附加了ListModel。

无论何时您需要列表,您都可以通过CartModel获得它。

我是怎么改变的?

  1. 将类果树拆分为一个单独的文件。// objects.dart
  2. 将ListModel转化为扩展模型的抽象ShoppingModel
  3. 创建了一个单例SuperModel,它用ShoppingModel和CartModel扩展了模型。给它一个私有构造函数和一个实例属性。这个对象将永远只有一个实例。SuperModel是一种混合,它能够访问ShoppingModel和CartModel的所有公共属性。为了避免编辑器显示的错误,添加了//analysis_options.yaml文件来抑制错误。注意:这不影响程序,您可以在网上找到更多有关它的信息。
  4. CartModel扩展了ShoppingModel,现在CartModel可以访问ShoppingModel的所有方法,而不必存储ListModel。使用ShoppingModel添加可能必须跨多个模型使用的属性。
  5. 将应用程序包装在ScopeModel中,模型属性是SuperModel。因为SuperModel是我使用的SuperModel.instance的单例,所以它从来不需要实例化。
  6. 在所有可能发生更改的地方添加ScopedModelDescendant,不要忘记rebuildOnChange: true,属性。

我还向您提供了存储库的所有者。

通常,在使用多个模型时,如果需要交换属性,则使用继承和混合。我总是使用一个顶级抽象模型子类,它保存所有其他模型使用的所有数据。其他模型扩展了这个类,以便能够访问这些属性。

但是,由于我们需要通过应用程序访问它们的属性,而抽象模型的后代不知道它们的子代,所以我们可以创建所有模型的混合体--在本例中是SuperModel。因为我们将永远需要一个实例,使它成为一个Singleton

代码语言:javascript
复制
class SuperModel extend Model with Model1, Model2{

  SuperModel._privateConstructor();

  static final SuperModel _instance = SuperModel._privateConstructor();

  static SuperModel get instance {
    return _instance;
  }

}

现在我们可以将SuperModel传递给ScopedModel。

若要启用无错误混合器,请添加:

代码语言:javascript
复制
analyzer:
  strong-mode: true
  language:
    enableSuperMixins: true

到pubspec.yaml文件的末尾

和一个新的根文件analysis_options.yaml:

代码语言:javascript
复制
analyzer:
  errors: 
    mixin_inherits_from_not_object: ignore

这适用于Visual代码,我不知道这对于Android是否有不同的处理方式

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60380903

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档