Как преобразовать поток до того, как он достигнет StreamBuilder?

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

import 'package:flutter/material.dart';

final Color darkBlue = Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: MyWidget(),
        ),
      ),
    );
  }
}

Stream<int> countDown() async* {
    int i = 42;
    while (true) {
      await Future.delayed(Duration(seconds: 1));
      yield i--;
      if (i == 0) break;
    }
  }

// Stream<String> countDownConverter() {
//   final number = countDown();
//   return number.toString();
// }

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
    stream: countDown(), // <- want countDownConverter() here
    builder: (context, snapshot) {
      if (snapshot.connectionState == ConnectionState.active) {
        final String count = snapshot.data.toString();
        return Text(count, style: Theme.of(context).textTheme.headline4);
      } else return Text('Working...');
    });
  }
}

person buttonsrtoys    schedule 04.02.2021    source источник
comment
используйте метод Stream.map, например var mapped = countDown().map((i) => i.toString());, теперь вы можете использовать stream: mapped   -  person pskink    schedule 04.02.2021
comment
Спасибо @pskink. Мой реальный вариант использования - это преобразование json из Firestore в мои локальные модели. Я бы хотел выполнить преобразование в моей модели ViewModel, а не использовать json в моем коде Flutter View, если это имеет смысл   -  person buttonsrtoys    schedule 04.02.2021
comment
вот почему я написал var mapped = countDown().map((i) => i.toString());, а не stream: countDown().map((i) => i.toString()), - просто вызовите метод map, в котором вы получаете свой firestore Stream (блок, провайдер и т. д.) - другими словами: сопоставьте свой firestore Stream с другим Stream   -  person pskink    schedule 04.02.2021
comment
Ах. Идеально. Спасибо!   -  person buttonsrtoys    schedule 04.02.2021


Ответы (1)


Преобразуйте countDownConverter в асинхронный генератор и используйте await for, чтобы он слушал countDown:

Stream<String> countDownConverter() async* {
  await for (int n in countDown()) {
    yield n.toString();
  }
}

Хотя в идеале вместо написания метода преобразования вы могли бы просто использовать map в самом потоке:

StreamBuilder(
  stream: countDown().map((i) => i.toString()),
  ...
),
person Abion47    schedule 04.02.2021
comment
Спасибо @ Abion47. Это идеально. Когда вы говорите об идеальном использовании map, это потому, что в нем меньше нажатий клавиш, или есть еще одно преимущество? - person buttonsrtoys; 04.02.2021
comment
@buttonsrtoys Это идеально, потому что, когда есть готовая функция, которая служит вашим целям, не изобретайте велосипед. - person Abion47; 05.02.2021