在 Flutter bloc 中管理 onBackPressed 的状态
Posted
技术标签:
【中文标题】在 Flutter bloc 中管理 onBackPressed 的状态【英文标题】:Managing state for onBackPressed in Flutter bloc 【发布时间】:2020-02-28 22:39:37 【问题描述】:所以我有一个可点击的简单列表并转到 DetailScreen,我遇到的问题是当我从 DetailScreen 中单击返回时,如何管理此状态以保存最后一个列表?
集团
if (event is GetNews && !_hasReachedMax(state))
try
if (currentState is NewsInitial)
final news = await fetchNews(event.cat, pageNumber);
yield NewsLoaded(news, false);
if (currentState is NewsLoaded)
pageNumber++;
final news = await fetchNews(event.cat, pageNumber);
yield news.isEmpty
? currentState.copyWith(hasReachedMax: true)
: NewsLoaded(currentState.node + news, false);
catch (error)
print(error);
yield NewsError("Error fetching news" + error);
else if (event is GetDetailedNews)
try
final filter = await fetchDetailedNews(event.id);
yield DetailedNewsLoaded(filter);
catch (error)
yield NewsError("Couldn't fetch news : $error");
将事件附加到集团
@override
void initState()
super.initState();
_postBloc = BlocProvider.of<NewsBloc>(context)
..add(GetNews(widget.cat));
块生成器
OnBackPressed 我只是坚持else
,因为我不知道如何管理状态
return BlocBuilder<NewsBloc, NewsState>(builder: (context, state)
if (state is NewsLoaded)
return ListView.builder(
controller: _scrollController,
itemCount: state.hasReachedMax
? state.node.length
: state.node.length + 1,
itemBuilder: (context, index)
fullList = state.node;
print("list: $state.node \nlength: $state.node
.length \nindex: $index \n--------------");
return index >= state.node.length ?
BottomLoader() :
listViews(context, state.node[index], index);
);
else if (state is NewsError)
return Center(
child: Container(
child: Text(state.message),
));
else
return Center(child: CircularProgressIndicator(),);
);
国家
abstract class NewsState extends Equatable
const NewsState();
@override
List<Object> get props => [];
class NewsInitial extends NewsState
const NewsInitial();
@override
List<Object> get props => [];
class NewsLoading extends NewsState
const NewsLoading();
@override
List<Object> get props => [];
class NewsLoaded extends NewsState
final List<Node> node;
final bool hasReachedMax;
NewsLoaded(this.node, this.hasReachedMax);
NewsLoaded copyWith(List<Node> node, bool hasReachedMax)
return NewsLoaded(node ?? this.node, hasReachedMax ?? this.hasReachedMax);
@override
List<Object> get props => [node];
class DetailedNewsLoaded extends NewsState
final List<Node> node;
DetailedNewsLoaded(this.node);
@override
List<Object> get props => [node];
在详细信息屏幕中,我添加了 GetDetailScreen 事件,该事件在 onBackPressed 时保持
@override
void initState()
BlocProvider.of<NewsBloc>(context)
..add(GetDetailedNews(widget.id));
super.initState();
【问题讨论】:
在哪里实例化 NewsBloc 对象?我在代码中看不到。确保您没有在 build 函数中执行此操作。 @IgorKharakhordin 我在 initState 中添加了事件,就像上面的代码一样。 【参考方案1】:我认为问题在于您按下查看文章时的状态变为DetailedNewsLoaded
。因此,当您按下 BlocBuilder<NewsBloc, NewsState>
时,会进入返回 CircularProgressIndicator
的 else 状态。
据我了解,在您的情况下,您不需要 DetailedNewsLoaded
状态。您只需将 state.node 作为简单参数传递给DetailsScreen
。
【讨论】:
这是两个不同的 API 端点,我使用DetailNewsLoaded
按 id 加载新闻,返回单个文章。
好的,我明白了。所以如果你print(state)
;在blocBuilder
里面,我相信你会看到状态是DetailedNewsLoaded
。这就是问题出现的地方。也许您可以考虑在您的情况下创建两个不同的集团。一个NewsBloc
用于您的新闻列表,另一个DetailsNewBloc
用于每篇文章。然后,当您按下按钮查看文章时,您可以使用BlocProvider( builder: (BuildContext context) => DetailsNewBloc()..add(LoadArticle(id)), child: DetailsScreen(), );
也许你已经检查过了,但无论如何,我认为你可以再次看到 todos 应用程序如何使用示例中的状态和事件bloclibrary.dev/#/fluttertodostutorial?id=states 我认为它非常接近你想要做的事情.希望对你有帮助【参考方案2】:
当你已经在 Flutter 中拥有 hero widget 时,为什么要做这么多。
-
列个清单。
对列表项及其详细信息视图使用英雄动画。
只要单击列表项,就会显示详细信息视图。
当用户按下后退按钮时,他/她将来到该特定列表项所在的位置。
所以,基本上你不需要太多。
我正在经历一些项目,我在 github 上找到了这个:https://github.com/whatsupcoders/Flutter-Hero-Widget
这个项目在我在 YouTube 上找到的这个视频中进行了介绍:https://www.youtube.com/watch?v=mgSB5r11_Xw&t=15s
本项目使用 Hero 小部件,希望对您有所帮助。
【讨论】:
目标是学习和实践如何为更大的项目实施 Bloc 库。所以代码在未来更容易升级/更改。 好的,那么这似乎对你没有帮助。以上是关于在 Flutter bloc 中管理 onBackPressed 的状态的主要内容,如果未能解决你的问题,请参考以下文章