Управление состоянием для onBackPressed в блоке Flutter - PullRequest
1 голос
/ 03 ноября 2019

Итак, у меня есть простой список, по которому можно кликнуть, и он переходит к 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));
  }

BlocBuilder

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

Ответы [ 2 ]

1 голос
/ 03 ноября 2019

Я считаю, что проблема в том, что ваше состояние, когда вы нажимаете, чтобы увидеть статью, меняется на DetailedNewsLoaded. Поэтому, когда вы нажимаете назад BlocBuilder<NewsBloc, NewsState>, вы переходите в другое состояние, которое возвращает CircularProgressIndicator.

Как я понимаю, в вашем случае вам не нужно состояние DetailedNewsLoaded. Вам просто нужно передать state.node в DetailsScreen в качестве простого аргумента.

0 голосов
/ 03 ноября 2019

Зачем делать так много, когда у вас уже есть виджет героя во Флаттере.

  1. Создание списка.
  2. Использование анимации героя для обоих элементов спискаи их подробное представление.
  3. При каждом нажатии на элемент списка будет отображаться подробное представление.
  4. Когда пользователь нажимает кнопку «Назад», он / она приходит в положение, в котором находился конкретный элемент списка. .

Итак, в основном вам не нужно много.

Я работал над некоторыми проектами и нашел это на github: https://github.com/whatsupcoders/Flutter-Hero-Widget

ЭтоПроект описан в этом видео, которое я нашел на YouTube: https://www.youtube.com/watch?v=mgSB5r11_Xw&t=15s

В этом проекте используется виджет Hero, надеюсь, он вам поможет.

...