我需要为我的应用程序创建体系结构的帮助。我正在使用Flutter和 scoped_model 来维持状态。
这是一个具有登录名的应用程序,它在该应用程序的一部分中显示新闻,并在其中显示照片库。我想将整个过程分解为单独的模型。拥有登录状态(例如用户名,令牌,名称等)的LoginModel。包含从API检索的新闻的NewsModel。 GalleryModel用来保存照片等的名称。我不确定这是否是使用scoped_model维护状态的最佳实践。
例如,如果文本框同时依赖LoginModel和NewsModel怎么办?我不确定,但是我想不可能从两个单独的模型中检索状态。 另外,我维护单独的模型以保持状态的主要原因是,我不希望在收到新闻时刷新应用程序的“登录”部分。我想将整个状态放在一个模型中就是这样。
答案 0 :(得分:10)
scoped_model
库旨在与多个模型同时运行。这是ScopedModel
和ScopedModelDescendant
是泛型且具有类型参数的部分原因。您可以使用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()),
),
),
],
),
),
)
答案 1 :(得分:5)
我想给你一个关于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