8

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

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

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

4

2 回答 2

13

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()),
              ),
        ),
      ],
    ),
  ),
)
于 2018-06-28T15:25:01.253 回答
4

我想给你一个关于 ScopedModel 的简单例子。

pubspec.yaml 文件必须包括:-

dependencies:
  scoped_model: ^1.0.1

然后,

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(), //new class MyHomePage
    );
  }
}

//-----------------------------------CounterModel [used by ScopedModel]
class CounterModel extends Model {
  int _counter = 0;
  int get counter => _counter;
  void increment() {
    _counter++;
    notifyListeners();
  }
}
//-----------------------------------ends


//-----------------------------------MyHomePage class
class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return ScopedModel(    // ScopedModel used on top of the widget tree [it is wrapping up scaffold]
      model: CounterModel(), // providing the CounterModel class as model
      child: Scaffold(
        appBar: AppBar(),
        body: Container(
          child: ScopedModelDescendant<CounterModel>(  // ScopedModelDescendant accessing the data through ScopedModel
            builder: (context, _, model) => Text("${model._counter}"), // fetching data from model without thinking of managing any state.
          ),
        ),
        floatingActionButton: ScopedModelDescendant<CounterModel>(
          builder: (context, _, model) => FloatingActionButton(
                onPressed: model.increment, // calling function of model to increment counter
              ),
        ),
      ),
    );
  }
}
//-----------------------------------ends
于 2018-12-27T09:07:37.890 回答