Как использовать Pagview PageController во Flutter, используя Redux - PullRequest
0 голосов
/ 25 февраля 2019

Я использую Redux во Flutter (и я только начинаю изучать оба).Я пытался выяснить, как переключаться между страницами PageView с помощью PageController PageView.

Однако всякий раз, когда я пытаюсь использовать функцию PageController.jumpToPage (), я получаю исключение, заявляющее:

"При завершении дерева виджета было выброшено следующее утверждение: setState () или markNeedsBuild() вызывается, когда дерево виджетов было заблокировано. "

Когда я пытаюсь вызвать PageController.jumpToPage () в моем редукторе, он переходит на страницу в просмотре страницы;но исключение выдается.

Я также попытался просто создать новый PageController в редукторе и просто установить свойство начальной страницы PageController на нужную страницу, но это, похоже, ничего не дало.

У меня закончились идеи о том, как это выяснить самостоятельно, поэтому я решил спросить здесь.Буду признателен за любую помощь.

Я собрал быстрый образец, показывающий, что я пытаюсь сделать:

import 'package:flutter/material.dart';
import 'package:redux/redux.dart';
import 'package:flutter_redux/flutter_redux.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  final store = Store<AppState>(appReducer,
      initialState: AppState.initial(), middleware: []);

  @override
  Widget build(BuildContext context) {
    return StoreProvider(
      store: store,
      child: MaterialApp(
        title: 'PageView Example With Redux',
        home: MyPageViewContainer(),
      ),
    );
  }
}

class AppState {
  final List<Widget> pageViewList;
  final PageController pageController;

  AppState({
    this.pageViewList,
    this.pageController,
  });

  factory AppState.initial() {
    return AppState(
      pageViewList: [
        PageOne(),
        PageTwo(),
      ],
      pageController: PageController(initialPage: 0),
    );
  }

  AppState copyWith({
    List<Widget> pageViewList,
    PageController pageController,
  }) {
    return AppState(
      pageViewList: pageViewList ?? this.pageViewList,
      pageController: pageController ?? this.pageController,
    );
  }
}

AppState appReducer(AppState state, action) {   

  if (action is NavigateToPageOneAction) {
      state.pageController.jumpToPage(0);
    return state;
  }
  else if (action is NavigateToPageTwoAction) {
    state.pageController.jumpToPage(1);
    return state;
  }
  else {
    return state;
  }      
}

class NavigateToPageOneAction {}

class NavigateToPageTwoAction {}

class MyPageView extends StatelessWidget {
  final List<Widget> pageViewList;
  final PageController pageController;
  final Function onPageChanged;

  MyPageView({
    this.pageViewList,
    this.pageController,
    this.onPageChanged,
  });

  @override
  Widget build(BuildContext context) {
    return PageView(
      controller: pageController,
      children: pageViewList,
      onPageChanged: onPageChanged,
    );
  }
}

class MyPageViewContainer extends StatelessWidget {
  MyPageViewContainer({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return StoreConnector<AppState, _MyPageViewModel>(
      converter: (Store<AppState> store) => _MyPageViewModel.create(store),
      builder: (BuildContext context, _MyPageViewModel vm) {
        return MyPageView(
          pageViewList: vm.pageViewList,
          pageController: vm.pageController,
        );
      },
    );
  }
}

class _MyPageViewModel {
  final List<Widget> pageViewList;
  final PageController pageController;
  final Function onPageChanged;

  _MyPageViewModel({
    this.pageViewList,
    this.pageController,
    this.onPageChanged,
  });

  factory _MyPageViewModel.create(Store<AppState> store) {
    _onPageChanged() {}

    return _MyPageViewModel(
      pageViewList: store.state.pageViewList,
      pageController: store.state.pageController,
      onPageChanged: _onPageChanged(),
    );
  }
}

class PageOne extends StatelessWidget {
  PageOne();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Page One"),
      ),
      backgroundColor: Colors.black,
      body: Column(),
      drawer: MyDrawer(),
    );
  }
}

class PageTwo extends StatelessWidget {
  PageTwo();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Page Two"),
      ),
      backgroundColor: Colors.blue,
      body: Column(),
      drawer: MyDrawer(),
    );
  }
}

class MyDrawer extends StatelessWidget {
  MyDrawer({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return StoreConnector<AppState, _MyDrawerViewModel>(
      converter: (Store<AppState> store) => _MyDrawerViewModel.create(store),
      builder: (BuildContext context, _MyDrawerViewModel vm) {
        return Drawer(
          child: ListView(
            children: <Widget>[
              Container(
                child: ListTile(
                  title: Text(vm.pageOneText),
                  onTap: vm.pageOneOnTap,
                ),
              ),
              Container(
                child: ListTile(
                  title: Text(vm.pageTwoText),
                  onTap: vm.pageTwoOnTap,
                ),
              ),
            ],
          ),
        );
      },
    );
  }
}

class _MyDrawerViewModel {
  final String pageOneText;
  final String pageTwoText;
  final Function pageOneOnTap;
  final Function pageTwoOnTap;

  _MyDrawerViewModel({
    this.pageOneText,
    this.pageTwoText,
    this.pageOneOnTap,
    this.pageTwoOnTap,
  });

  factory _MyDrawerViewModel.create(Store<AppState> store) {
    _goToPageOne() {

     store.dispatch(NavigateToPageOneAction());
    }

   _goToPageTwo() {

     store.dispatch(NavigateToPageTwoAction());
   }

    return _MyDrawerViewModel(
      pageOneText: "Page One",
      pageTwoText: "Page Two",
      pageOneOnTap: _goToPageOne,
      pageTwoOnTap: _goToPageTwo,
    );
  }
}

Ответы [ 2 ]

0 голосов
/ 28 февраля 2019

@ Blau

Иногда событие происходило за пределами созданных вами виджетов.например, (1) Таймер, который увеличивает «Глобальный счетчик», этот счетчик будет отображаться на многих страницах / виджетах (2) Сообщение, отправленное с сервера сокетов, при получении этого сообщения / события пользователь может находиться где угодно (любые страницы/ widgets), и вы не знаете, где 'setState' (или виджета на самом деле нет, потому что пользователь не на этой странице)

Я построил 2 примера, которые демонстрируют, как использовать ReduxЧтобы решить проблемы такого рода:

Пример 1: (Использование многопоточного таймера для установки виджета при запуске внешнего события)

https://github.com/lhcdims/statemanagement01

Пример 2: (Используйте Redux для обновления виджета при срабатывании внешнего события)

https://github.com/lhcdims/statemanagement02

Демонстрационный снимок экрана:

enter image description here

0 голосов
/ 27 февраля 2019

Кажется, я понял, как решить мою проблему.Я видел ответ в этом посте: Flutter: setState () или markNeedsBuild () вызывается, когда дерево виджетов было заблокировано ... во время изменения ориентации

В этом посте OP сталкивался с тем жеошибка при переключении между портретным и ландшафтным режимами, когда ящик был открыт.В ответе на этот пост предлагалось вызвать Navigator.pop () (который закрывает ящик) перед сменой режимов просмотра.

Поэтому я попытался закрыть свой ящик с помощью Navigator.pop () перед использованиемМетод PageController .jumpToPage.Кажется, это работает, и позволяет мне перемещаться между страницами PageView, используя события onTap из Drawer, не выбрасывая «При завершении дерева виджета было выдано следующее утверждение: setState () или markNeedsBuild () вызывается, когда дерево виджетов было заблокировано"исключение.

Я предполагаю, что это означает, что, пока ящик открыт, дерево виджетов переводится в заблокированное состояние.

Надеюсь, это кому-то поможет, поскольку мне потребовалось некоторое время, чтобы понятьвне.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...