Flutter 颤振提供者/使用者UI未随数据更改而更新
我是一个新手,正在开发我的第一个应用程序。根据数据更改更新UI时遇到问题。我遵循了本教程:(并添加了额外的特性),该教程使用GetIt库遍历MVVM设置 我已成功地通过viewmodels和services传递了数据,但无法更新UI。本质上,我希望用户能够点击他们观察列表上的电影并将其删除。这在数据意义上是有效的,但当我返回时,我的监视列表UI并没有更新。我的整个项目可在上获得,但此问题的核心文件如下所示: 定位镖 监视列表\u服务.dartFlutter 颤振提供者/使用者UI未随数据更改而更新,flutter,dart,Flutter,Dart,我是一个新手,正在开发我的第一个应用程序。根据数据更改更新UI时遇到问题。我遵循了本教程:(并添加了额外的特性),该教程使用GetIt库遍历MVVM设置 我已成功地通过viewmodels和services传递了数据,但无法更新UI。本质上,我希望用户能够点击他们观察列表上的电影并将其删除。这在数据意义上是有效的,但当我返回时,我的监视列表UI并没有更新。我的整个项目可在上获得,但此问题的核心文件如下所示: 定位镖 监视列表\u服务.dart 。。。 ... 类WatchlistService{
。。。
...
类WatchlistService{
Api_Api=定位器();
列表_watchlist=[];
List get watchlist=>\u watchlist;
未来getUserWatchlist(用户)异步{
for(user.watchlistId中的字符串id){
_add(wait_api.getMovie(id));
}
}
布尔因利斯特(电影){
return_watchlist.contains(电影);
}
作废编辑列表(电影、bool-remove){
如果(删除){
_监视列表。删除(电影);
打印(“从监视列表服务中的列表中删除”+movie.title+”);
}否则{
_添加(电影);
打印(“将“+movie.title+”添加到观察列表服务的列表中”);
}
}
}
监视列表\u型号dart
。。。
...
类WatchlistModel扩展了BaseModel{
WatchlistService_WatchlistService=locator();
List get watchlist=>\u watchlistService.watchlist;
未来getWatchlist(用户)异步{
设置状态(ViewState.Busy);
wait_watchlistService.getUserWatchlist(用户);
设置状态(ViewState.Idle);
}
}
监视列表\u view.dart
。。。
...
类WatchlistView扩展了无状态小部件{
小部件_createMovieCard(电影、构建上下文){
返回CupertinoButton(
按下:()=>\u获取信息(电影、上下文),
孩子:图像.网络(电影.海报(185)),
);
}
_getInfo(电影、构建上下文){
Navigator.pushNamed(
上下文
“详情”,
论点:电影,
);
}
@凌驾
小部件构建(构建上下文){
返回基本视图(
onModelReady:(model)=>model.getWatchlist(Provider.of(context)),
生成器:(上下文、模型、子项)=>Scaffold(
正文:model.state==ViewState.Idle
?自定义滚动视图(
主要:错误,
条子:[
CupertinoSliverNavigationBar(
largeTitle:Text(“我的观察列表”),
尾随:材料(
颜色:颜色。透明,
孩子:我的钮扣(
图标:图标(CupertinoIcons.添加圆形实体),
按下:()=>
Navigator.pushNamed(上下文“搜索”),
),
银栅(
gridDelegate:SliverGridDelegateWithFixedCrossAxisCount(
交叉轴计数:2,
儿童方面:
MediaQuery.of(context).size.width/
(MediaQuery.of(context.size.height/1.7)),
代表:SliverChildBuilderDelegate(
(BuildContext上下文,int索引){
返回_createMovieCard(
监视列表[索引],上下文);
},childCount:model.watchlist.length),
),
],
)
:居中(子项:CircularProgressIndicator());
}
}
删除btn_model.dart
。。。
...
类RemoveButtonModel扩展了BaseModel{
WatchlistService_WatchlistService=locator();
//bool watchlistStatus()
无效移除电影(电影){
打印(“从移除按钮模型中的列表中移除“+movie.title+”);
_editList(电影,真);
notifyListeners();
}
void addMovie(电影){
打印(“将“+movie.title+”添加到移除按钮模型中的列表中”);
_editList(电影,false);
notifyListeners();
}
}
详细信息\u view.dart
。。。
...
类DetailsView扩展了无状态小部件{
_makeStars(双平均值){
双精度=voteAverage/2;
印刷(真实化);
回报率(
颜色:颜色。黄色调[700],
价值:真实,
尺寸:GFSize.SMALL,
Allowalflating:是的,
);
}
_背景(字符串链接){
如果(链接!=null){
返回Image.network(“http://image.tmdb.org/t/p/w780/$link”);
}否则
返回Image.asset(“assets/images/transparent.png”);
}
@凌驾
小部件构建(构建上下文){
Movie Movie=ModalRoute.of(context).settings.arguments;
返回脚手架(
正文:自定义滚动视图(
条子:[
CupertinoSliverNavigationBar(
largeTitle:文本(电影名称),
尾随:
材质(颜色:Colors.transparent,子级:RemoveButton(电影)),
),
滑动双轴适配器(
子:列(
儿童:[
填充(填充:仅限边集(顶部:20)),
中心(儿童:Image.network(movie.getPoster(342)),
居中(
子:容器(
填充:边缘设置。全部(10),
儿童:中心(
孩子:文本(movie.title,
textAlign:textAlign.center,
样式:TextStyle(
fontSize:40,fontWeight:fontWeight.w800)),
)),
容器(
填充:仅限边缘设置(底部:10),
孩子:排(
mainAxisAlignment:mainAxisAlignment.space,
...
...
GetIt locator = GetIt.instance;
void setupLocator() {
locator.registerLazySingleton(() => AuthenticationService());
locator.registerLazySingleton(() => WatchlistService());
locator.registerLazySingleton(() => Api());
locator.registerLazySingleton(() => LoginModel());
locator.registerFactory(() => HomeModel());
locator.registerFactory(() => RemoveButtonModel());
locator.registerFactory(() => WatchlistModel());
}
...
...
class WatchlistService {
Api _api = locator<Api>();
List<Movie> _watchlist = [];
List<Movie> get watchlist => _watchlist;
Future getUserWatchlist(User user) async {
for (String id in user.watchlistId) {
_watchlist.add(await _api.getMovie(id));
}
}
bool inList(Movie movie) {
return _watchlist.contains(movie);
}
void editList(Movie movie, bool remove) {
if (remove) {
_watchlist.remove(movie);
print("removed " + movie.title + " from list in watchlist service");
} else {
_watchlist.add(movie);
print("added " + movie.title + " to list in watchlist service");
}
}
}
...
...
class WatchlistModel extends BaseModel {
WatchlistService _watchlistService = locator<WatchlistService>();
List<Movie> get watchlist => _watchlistService.watchlist;
Future getWatchlist(User user) async {
setState(ViewState.Busy);
await _watchlistService.getUserWatchlist(user);
setState(ViewState.Idle);
}
}
...
...
class WatchlistView extends StatelessWidget {
Widget _createMovieCard(Movie movie, BuildContext context) {
return CupertinoButton(
onPressed: () => _getInfo(movie, context),
child: Image.network(movie.getPoster(185)),
);
}
_getInfo(Movie movie, BuildContext context) {
Navigator.pushNamed(
context,
"details",
arguments: movie,
);
}
@override
Widget build(BuildContext context) {
return BaseView<WatchlistModel>(
onModelReady: (model) => model.getWatchlist(Provider.of<User>(context)),
builder: (context, model, child) => Scaffold(
body: model.state == ViewState.Idle
? CustomScrollView(
primary: false,
slivers: <Widget>[
CupertinoSliverNavigationBar(
largeTitle: Text("My Watchlist"),
trailing: Material(
color: Colors.transparent,
child: IconButton(
icon: Icon(CupertinoIcons.add_circled_solid),
onPressed: () =>
Navigator.pushNamed(context, 'search'))),
),
SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio:
MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 1.7)),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return _createMovieCard(
model.watchlist[index], context);
}, childCount: model.watchlist.length),
),
],
)
: Center(child: CircularProgressIndicator())));
}
}
...
...
class RemoveButtonModel extends BaseModel {
WatchlistService _watchlistService = locator<WatchlistService>();
//bool watchlistStatus()
void removeMovie(Movie movie) {
print("removed " + movie.title + " from list in remove button model");
_watchlistService.editList(movie, true);
notifyListeners();
}
void addMovie(Movie movie) {
print("added " + movie.title + " to list in remove button model");
_watchlistService.editList(movie, false);
notifyListeners();
}
}
...
...
class DetailsView extends StatelessWidget {
_makeStars(double voteAverage) {
double trueRating = voteAverage / 2;
print(trueRating);
return GFRating(
color: Colors.yellowAccent[700],
value: trueRating,
size: GFSize.SMALL,
allowHalfRating: true,
);
}
_backdrop(String link) {
if (link != null) {
return Image.network("http://image.tmdb.org/t/p/w780/$link");
} else
return Image.asset("assets/images/transparent.png");
}
@override
Widget build(BuildContext context) {
Movie movie = ModalRoute.of(context).settings.arguments;
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
CupertinoSliverNavigationBar(
largeTitle: Text(movie.title),
trailing:
Material(color: Colors.transparent, child: RemoveButton(movie)),
),
SliverToBoxAdapter(
child: Column(
children: <Widget>[
Padding(padding: EdgeInsets.only(top: 20)),
Center(child: Image.network(movie.getPoster(342))),
Center(
child: Container(
padding: EdgeInsets.all(10),
child: Center(
child: Text(movie.title,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 40, fontWeight: FontWeight.w800))),
)),
Container(
padding: EdgeInsets.only(bottom: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
_makeStars(movie.voteAverage),
Text("platform",
style: Theme.of(context).textTheme.headline5),
],
),
),
Container(
padding: EdgeInsets.fromLTRB(20, 0, 10, 50),
child: Text(movie.overview),
),
_backdrop(movie.backdropPath)
],
))
],
),
);
}
}
...
...
class RemoveButton extends StatelessWidget {
final Movie movie;
RemoveButton(this.movie);
_showDialog(String id, bool inWatchlist, BuildContext context,
RemoveButtonModel model) {
if (inWatchlist) {
showDialog(
context: context,
child: CupertinoAlertDialog(
title: Text("Remove from your watchlist?"),
actions: <Widget>[
CupertinoDialogAction(
isDefaultAction: true,
onPressed: () =>
Navigator.of(context, rootNavigator: true).pop(),
child: Text("Cancel"),
),
CupertinoDialogAction(
textStyle: TextStyle(color: Colors.red),
onPressed: () => _deletelist(id, context, model),
child: Text("Remove"),
)
]));
} else {
showDialog(
context: context,
child: CupertinoAlertDialog(
title: Text("Add to your watchlist?"),
actions: <Widget>[
CupertinoDialogAction(
onPressed: () =>
Navigator.of(context, rootNavigator: true).pop(),
child: Text("Cancel"),
),
CupertinoDialogAction(
isDefaultAction: true,
onPressed: () => _addList(id, context, model),
child: Text("Add"),
)
]));
}
}
_deletelist(String id, BuildContext context, RemoveButtonModel model) {
model.removeMovie(movie);
Provider.of<User>(context).deleteFromWatchlist(id);
//Navigator.pushNamed(context, 'watchlist');
Navigator.popUntil(context, ModalRoute.withName('watchlist'));
}
_addList(String id, BuildContext context, RemoveButtonModel model) {
model.addMovie(movie);
Provider.of<User>(context).addToWatchList(id);
Navigator.popUntil(context, ModalRoute.withName('watchlist'));
}
Widget _rightBtn(Movie movie, BuildContext context, RemoveButtonModel model) {
if (Provider.of<User>(context).inWatchlist(movie)) {
return IconButton(
icon: Icon(Icons.remove_circle),
color: Colors.blue,
onPressed: () =>
_showDialog(movie.id.toString(), true, context, model));
} else {
return IconButton(
icon: Icon(Icons.add_circle),
color: Colors.blue,
onPressed: () =>
_showDialog(movie.id.toString(), false, context, model));
}
}
@override
Widget build(BuildContext context) {
return BaseView<RemoveButtonModel>(
builder: (context, model, child) => _rightBtn(movie, context, model),
);
}
}