【问题标题】:Managing state for onBackPressed in Flutter bloc在 Flutter bloc 中管理 onBackPressed 的状态
【发布时间】: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 中添加了事件,就像上面的代码一样。

标签: flutter bloc


【解决方案1】:

我认为问题在于您按下查看文章时的状态变为DetailedNewsLoaded。因此,当您按下 BlocBuilder&lt;NewsBloc, NewsState&gt; 时,会进入返回 CircularProgressIndicator 的 else 状态。

据我了解,在您的情况下,您不需要 DetailedNewsLoaded 状态。您只需将 state.node 作为简单参数传递给DetailsScreen

【讨论】:

  • 这是两个不同的 API 端点,我使用 DetailNewsLoaded 按 id 加载新闻,返回单个文章。
  • 好的,我明白了。所以如果你print(state);在blocBuilder 里面,我相信你会看到状态是DetailedNewsLoaded。这就是问题出现的地方。也许您可以考虑在您的情况下创建两个不同的集团。一个NewsBloc 用于您的新闻列表,另一个DetailsNewBloc 用于每篇文章。然后,当您按下按钮查看文章时,您可以使用BlocProvider( builder: (BuildContext context) =&gt; DetailsNewBloc()..add(LoadArticle(id)), child: DetailsScreen(), );
  • 也许你已经检查过了,但无论如何,我认为你可以再次看到 todos 应用程序如何使用示例中的状态和事件bloclibrary.dev/#/fluttertodostutorial?id=states 我认为它非常接近你想要做的事情.希望对你有帮助
【解决方案2】:

当你已经在 Flutter 中拥有 hero widget 时,为什么要做这么多。

  1. 列个清单。
  2. 对列表项及其详细信息视图使用英雄动画。
  3. 只要单击列表项,就会显示详细信息视图。
  4. 当用户按下后退按钮时,他/她将来到该特定列表项所在的位置。

所以,基本上你不需要太多。

我正在经历一些项目,我在 github 上找到了这个:https://github.com/whatsupcoders/Flutter-Hero-Widget

这个项目在我在 YouTube 上找到的这个视频中进行了介绍:https://www.youtube.com/watch?v=mgSB5r11_Xw&t=15s

本项目使用 Hero 小部件,希望对您有所帮助。

【讨论】:

  • 目标是学习和实践如何为更大的项目实施 Bloc 库。所以代码在未来更容易升级/更改。
  • 好的,那么这似乎对你没有帮助。
猜你喜欢
  • 2021-03-04
  • 2019-08-04
  • 2021-04-14
  • 2020-03-10
  • 2021-12-23
  • 2020-06-15
  • 2023-01-05
  • 2020-08-01
  • 2021-03-19
相关资源
最近更新 更多