简体   繁体   English

使用Scoped模型来维持扑动中的应用状态

[英]Using Scoped Model to maintain app state in flutter

I need help creating the architecture for my application. 我需要帮助为我的应用程序创建架构。 I am using Flutter and scoped_model to maintain state. 我正在使用Flutter和scoped_model来维护状态。

It's an application that has a login, that displays news in one part of the application, and shows a photo gallery among others. 这是一个具有登录功能的应用程序,它在应用程序的一个部分中显示新闻,并显示照片库等。 I would like to split this entire thing into separate Models. 我想将整个事情分成不同的模型。 LoginModel that holds Login state (like username, token, name etc.). 保存登录状态的LoginModel(如用户名,令牌,名称等)。 NewsModel that contains news retrieved from the API. 包含从API检索的新闻的NewsModel。 GalleryModel to hold names of photos etc. I am not sure if this is the best practice to maintain state using scoped_model. GalleryModel用于保存照片的名称等。我不确定这是否是使用scoped_model维护状态的最佳实践。

For eg, what If a text box depends on both LoginModel and NewsModel? 例如,如果文本框依赖于LoginModel和NewsModel,该怎么办? I am not sure, but I guess it's not possible to retrieve state from two separate models. 我不确定,但我想从两个独立的模型中检索状态是不可能的。 Also, the main reason I am maintaining separate Models to hold state is that I don't want the Login part of the app to get refreshed when I bring news. 此外,我维护单独的模型以保持状态的主要原因是我不希望在我带来新闻时刷新应用程序的登录部分。 I guess that's how it goes when I put the entire state in a single model. 我猜这就是我将整个状态放在一个模型中的方式。

The scoped_model library is designed to work with multiple models in play at the same time. scoped_model库旨在同时处理多个模型。 That's part of the reason that ScopedModel and ScopedModelDescendant are generics and have a type parameter. 这是ScopedModelScopedModelDescendant是泛型并具有类型参数的部分原因。 You can define multiple models near the top of your Widget tree using ScopedModel<LoginModel> and ScopedModel<NewsModel> and then consume those models lower in the tree using ScopedModelDescendant<LoginModel> and ScopedModelDescendant<NewsModel> . 您可以使用ScopedModel<LoginModel>ScopedModel<NewsModel> ScopedModel<LoginModel>在Widget树顶部附近定义多个模型,然后使用ScopedModelDescendant<LoginModel>ScopedModelDescendant<NewsModel> ScopedModelDescendant<LoginModel>使用树中较低的模型。 The descendants will go looking for the appropriate model based on their type parameter. 后代将根据其类型参数寻找合适的模型。

I knocked together a quick example. 我敲了一个简单的例子。 Here are the models: 以下是模型:

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

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

And here's what I'm displaying in the app: 以下是我在应用中显示的内容:

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()),
                ),
              ],
            ),
          );
        },
      ),
    ),
  ),
)

It seems to be working just fine. 它似乎工作得很好。 A non-nested approach works as well: 非嵌套方法也适用:

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()),
              ),
        ),
      ],
    ),
  ),
)

I wanted to give you a simple example on ScopedModel. 我想在ScopedModel上给你一个简单的例子。

pubspec.yaml file must include :- pubspec.yaml文件必须包括: -

dependencies:
  scoped_model: ^1.0.1

then, 然后,

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM