我有一个带有tabBarView
的主页,其中包含2页,分别是首页和收藏夹。主页上有一个gridview
,其单元格由streambuilder
填充。单击时,他们使用导航器重定向到该单元格的详细信息页面。我可以在2个标签页之间切换。转到详细信息页面(从主页)并返回首页后,gridView
会正确显示其数据。但是之后,如果我转到“收藏夹”页面并返回首页,则gridView
数据将丢失。
我已经按照SO的建议尝试了AutomaticKeepAliveClientMixin
和wantKeepAlive = true
。
根据调试器的显示,首页小部件在与收藏夹之间切换时不会重建,并且数据显示正常。
从详细信息页面返回主页确实会重建主页,这在数据显示时也可以。只有在那之后我转到“收藏夹”选项卡并再次返回时,问题才会发生。
我正在使用Bloc模式,并且在主窗口小部件中引用了提供者的bloc。它将其传递给gridView
。
我在SliverAppBar中使用标准的tabBarView和Navigator。
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MovieProvider(
euCollBloc: EuThemeCollectionBloc(API()),
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(),
home: MyHomePage(),
),
);
}
}
body: TabBarView(
children: <Widget>[
PageOne(),
PageTwo(),
],
bottom: TabBar(
tabs: <Widget>[
Tab(
text: "Home",
icon: Icon(Icons.home),
),
Tab(
text: "Favorites",
icon: Icon(Icons.favorite),
),
],
controller: _tabController,
))
.......
导航器,在PageOne小部件中使用:
.......
return GridView.builder(
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemCount: snapshot.data.length,
itemBuilder: (context, index) => GestureDetector(
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => EuroCard(
preview: snapshot.data[index].preview ?? "",
title: snapshot.data[index].title,
description: snapshot.data[index].description,
),
));
},
child: Card(
.......
使用tensor在youtube上的教程中的提供程序和bloc代码(对我来说可能太高级了。)
集团:
class EuThemeCollectionBloc {
final API api;
Stream<List<EuThemeCollection>> _results = Stream.empty();
Stream<String> _log = Stream.empty();
ReplaySubject<String> _query = ReplaySubject<String>();
Stream<String> get log => _log;
Stream<List<EuThemeCollection>> get results => _results;
Sink<String> get query => _query;
EuThemeCollectionBloc(this.api) {
_results = _query.distinct().asyncMap(api.get).asBroadcastStream();
_log = Observable(results)
.withLatestFrom(_query.stream, (_, query) => 'Results for $query')
.asBroadcastStream();
}
void dispose() {
_query.close();
}
}
提供者:
class MovieProvider extends InheritedWidget {
final EuThemeCollectionBloc euCollBloc;
@override
bool updateShouldNotify(InheritedWidget oldWidget) => true;
static EuThemeCollectionBloc of(BuildContext context) =>
(context.inheritFromWidgetOfExactType(MovieProvider) as MovieProvider)
.euCollBloc;
MovieProvider({Key key, EuThemeCollectionBloc euCollBloc, Widget child})
: this.euCollBloc = euCollBloc ?? EuThemeCollectionBloc(API()),
super(child: child, key: key);
}
我尝试使用BehaviorSubject,但随后出现运行时错误,该错误指向主页中的查询流:
错误:未为类“ EuroCard”定义吸气剂“ euCollBloc”。 -“ EuroCard”来自“ package:bloc_example / euroCard.dart”(“ lib / euroCard.dart”)。 尝试将名称更正为现有吸气剂的名称,或者定义一个名为“ euCollBloc”的吸气剂或字段。
已修复: 我需要将super.build(context)添加到PageOne(GridView)小部件-它正在使用AutomaticKeepAliveClientMixin扩展State,因此需要重写。抱歉,原来根本没有张贴罪魁祸首。
class _PageOneState extends State<PageOne> with
AutomaticKeepAliveClientMixin<PageOne>{
@override
bool get wantKeepAlive => true;
Widget build(BuildContext context){
super.build(context);
var euCollBloc = MovieProvider.of(context);
答案 0 :(得分:0)
我似乎已经通过PageOne(GridView)小部件中的简单setState((){euCollBloc = euCollBloc)}修复了该问题。
我现在可以做我以前做不到的事情:加载显示带有数据单元格的Gridview的主页选项卡,然后导航到单元格详细信息页面并返回主页,切换到收藏夹页面,然后再次回到主页,并且数据仍然显示。
关于此问题的修复原因,我不确定。我认为Provider模式可以防止这样的setStates。