Как перезапустить асинхронную функцию в блоке, пока она работает?

Есть простой блок, в котором используется контроллер rxdart. Он не делает ничего, кроме потоковой передачи в целом. В этом есть логика, чтобы снова начать читать.

class ReaderBloc {
  bool started = false;
  final _publishStream = PublishSubject<String>();
  Stream<String> get publishStream => _publishStream.stream;

  startReading() async {
    List<String> lines = ['a','b','c','d','e','f','g','h'];

    for (String l in lines) {
      if (started) {
        started = false;
        _publishStream.done;
        break;
      }
      _publishStream.add(l);
      await Future.delayed(const Duration(milliseconds: 3000));
    }
  }

  dispose() {
    _publishStream.close();
  }
}

и представление, которое просто получает и отображает эти строки из блочной логики

class Reader extends StatefulWidget {
  const Reader({super.key});
  @override
  State<Reader> createState() => _ReaderState();
}

class _ReaderState extends State<Reader> {
  late ReaderBloc readerBloc;

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    readerBloc = Provider.of<ReaderBloc>(context);

    return DefaultTabController(
      length: 1,
      child: Scaffold(
        appBar: AppBar(
          actions: <Widget>[
            IconButton(
              icon: const Icon(
                Icons.refresh,
                color: Colors.white,
              ),
              onPressed: () {
                // seems this part doesn't work
                readerBloc.started = true;
                readerBloc.startReading();
              },
            )
          ],
        ),
        body: TabBarView(
          children: [
            Scaffold(body: tabBody(readerBloc.publishStream)),
          ],
        ),
      ),
    );
  }

  tabBody(Stream<String> stream) {
    return StreamBuilder<String>(
      stream: stream,
      builder: (context, snapshot) {
        if (!snapshot.hasData) {
          return const Center(child: CircularProgressIndicator());
        }
        return Text(
          snapshot.data.toString(),
        );
      },
    );
  }
}

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

Provider.of<ReaderBloc>(context, listen: false).startReading();
Navigator.of(context).push(MaterialPageRoute(builder: (context) => const Reader()));

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

Что я пропустил с этим, так это то, что он не работает должным образом?

Где часть вашего кода, которая должна остановить чтение?

Abion47 11.04.2023 23:28

@Abion47 см. комментарий Читателя // seems this part doesn't work и соответствующее условие в блоке с ключевым словом break.

rozerro 12.04.2023 07:30

Я не вижу в этом коде ничего, что могло бы остановить чтение, которое происходит. Я думаю, что недоразумение возникает из-за того, что на самом деле делает вызов асинхронного метода. Вызов того же метода не останавливает действие, которое было запущено ранее. Это как столкнуть валун с горы. Вы можете столкнуть с холма еще один валун, но это не остановит валун, который уже движется вниз. Все, что нужно сделать, это сделать так, чтобы теперь у вас было два валуна, катящихся с холма.

Abion47 13.04.2023 02:01

@Abion47 ты заметил флаг started? Разве асинхронная функция уже не видит значение измененного флага, когда мы нажимаем кнопку обновления?

rozerro 13.04.2023 07:20

Нет, потому что вы сразу вызываете startReading после этого, и этот вызов увидит это started == true и сломается задолго до того, как существующая операция выполнит эту проверку.

Abion47 13.04.2023 16:00
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
78
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

эти изменения решили проблему

ввиду:

onPressed: () {
    readerBloc.started = true;
},

в блоке:

if (started) {
    started = !started;
    startReading();
    break;
}

Другие вопросы по теме