【问题标题】:After using navigator in a tabBarView page data is lost在 tabBarView 页面中使用导航器后,数据丢失
【发布时间】:2019-08-24 23:36:00
【问题描述】:

我有一个带有 tabBarView 的主页,有 2 个页面,主页和收藏夹。主页有一个gridview,其单元格由streambuilder 填充。单击时,他们使用导航器重定向到该单元格的详细信息页面。我可以在 2 个标签页之间切换。转到详细信息页面(从主页)并返回主页后,gridView 会正确显示其数据。但在那之后,如果我转到收藏夹页面并返回主页,gridView 的数据就会丢失。

我已经按照 SO 上的建议尝试了 AutomaticKeepAliveClientMixinwantKeepAlive = true

根据调试器,在主页小部件和收藏夹之间切换时,主页小部件不会重建,并且数据显示正常。

从详细信息页面返回主页确实会重建主页,这在数据显示时也很好。只有在那之后我转到收藏夹选项卡并再次返回时才会出现问题。

我正在使用 bloc 模式,并在 home 小部件中引用了 Provider 的 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(
.......

使用 youtube 上 tensor 的教程中的提供程序和块代码(对我来说可能太高级了)。

集团:

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”)。 尝试将名称更正为现有 getter 的名称,或定义名为“euCollBloc”的 getter 或字段。

固定: 我需要将 super.build(context) 添加到 PageOne (GridView) 小部件 - 它使用 AutomaticKeepAliveClientMixin 扩展状态,因此需要被覆盖。抱歉,最初甚至没有发布罪魁祸首部分。


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);






【问题讨论】:

  • 给个代码示例而不是解释就好了!
  • 似乎没有设置默认值。您可能需要考虑使用BehaviorSubject,即使没有数据发送到流来触发构建,它也会保留以前的值。但是一些代码会有所帮助。
  • 感谢您的回复,我已添加代码。 (尝试了 BehaviorSubject,并得到关于未定义查询的 getter 的错误。)。希望有任何见解。

标签: flutter navigator


【解决方案1】:

我似乎已在 PageOne (GridView) 小部件中使用简单的 setState((){euCollBloc = euCollBloc)} 修复它。

我现在可以做我以前不能做的事情:加载显示带有数据单元格的 Gridview 的主页选项卡,然后导航到单元格详细信息页面并返回主页,选项卡到收藏夹页面,然后再次选项卡返回主页,数据仍然显示。

至于为什么会修复它,我不确定。我认为提供者模式可以防止这样的 setStates。

【讨论】:

  • 好吧,我通过将 super.build(context) 添加到 PageOne 小部件来修复它: class _PageOneState extends State with AutomaticKeepAliveClientMixin{ @override bool get wantKeepAlive => true;小部件构建(BuildContext 上下文){ super.build(context); var euCollBloc = MovieProvider.of(context);
猜你喜欢
  • 1970-01-01
  • 2013-12-10
  • 1970-01-01
  • 2018-12-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-06
  • 2014-12-09
相关资源
最近更新 更多