Flutter - Понимание жизненного цикла Provider, Bloc и когда удалять поток

Необходимо понять, когда мы должны использовать шаблон Bloc и жизненный цикл Bloc (как освободить объекты, содержащие память).

У меня есть экран, на котором я получаю данные с сервера, и данные будут использоваться только для одного экрана. Я использую шаблон Bloc для отображения данных.

При использовании шаблона Bloc у меня есть экран, на котором я использую StatelessWidget. Я пытаюсь избавиться от потока на WillPopScope. После удаления поток больше не может использоваться. Потому что посещение того же экрана приводит к сбою, поскольку я обернул свое приложение MaterialApp с помощью Bloc.

  1. создал поток
    final _leaderBoardList = StreamController<List<dynamic>>.broadcast();
  1. поток утилизации
    dispose() {
      print('_leaderBoardList disposed');
      _leaderBoardList.close();
    }
  1. обертывание приложения Material внутри провайдера:
    LeaderBoardProvider(
        child: MaterialApp(
        title: 'Table View Fetch',
        theme: ThemeData(
          primarySwatch: Colors.teal,
        ),
        home: HomeScreen(),
      ),
      );
  1. Statelesswidget 'WillPopScope', я прокомментировал удаление кода, поскольку в настоящее время блок создается один раз, как я понял:
  Widget build(BuildContext context) {

    print(' ListView fetch Build called');
    final bloc = LeaderBoardProvider.of(context);
    bloc.fetchLeaderBoards();
    return WillPopScope(
      onWillPop: () async {
        //bloc.dispose();
        return true;
      },
      child: bodyStack(context, bloc),
    );
  }

Первый вопрос. Предположим, я создаю широковещательный поток и удаляю удаление кода в WillPopScope, тогда все работает, как ожидалось, но я думаю, что таким образом мой блок будет хранить память на время жизни приложения.

Второй вопрос, как справиться с такими случаями, когда данные используются на экране. Рекомендуется ли шаблон Bloc для этой ситуации?


person Ankur Prakash    schedule 19.01.2019    source источник


Ответы (1)


Вы не должны удалять BLoC в пределах WillPopScope.

Работа вашего «провайдера» состоит в том, чтобы обрабатывать удаление вашего BLoC: он должен закрывать потоки, когда виджет провайдера удаляется из дерева.

Это достигается за счет того, что ваш Провайдер является StatefulWidget (с внутренним частным InheritedWidget для раскрытия BLoC) и переопределяет dispose метод.

См. Flutter: как правильно использовать унаследованный виджет? для примера (не имеет отношения к BLoC и не имеет dispose, но идея аналогична).

person Rémi Rousselet    schedule 19.01.2019
comment
Понятно, вы рекомендуете этот подход, на который вы ответили здесь, stackoverflow.com/a/51690319/2644723. - person Ankur Prakash; 20.01.2019
comment
Также в той же ссылке вы упомянули, что InheritedWidget ведет себя так же, как и другие виджеты. Их время жизни действительно короткое: обычно не больше одного вызова сборки. Если вы хотите хранить данные дольше, InheritedWidget - не то, что вам нужно. Для этого вам понадобится государство. Чтобы уточнить, здесь вы имеете в виду состояние с использованием GlobalKey в качестве ключа? - person Ankur Prakash; 20.01.2019
comment
Нет. Использование фактического подкласса State - person Rémi Rousselet; 20.01.2019
comment
_ViewControllerState createState() => _ViewControllerState(); } class _ViewControllerState extends State<ViewController> { `// здесь находится постоянное состояние виджета`` @ override` Widget build(BuildContext context) { // return a widget based on the persistent state `}` } Вы имеете в виду подкласс состояния? Не могли бы вы привести пример. - person Ankur Prakash; 20.01.2019