Как правильно реализовать StreamBuilder flutter

Я новичок в трепете. Я работаю над проектом, в котором я использовал Futurebuilder для получения данных с сервера, но сейчас я хотел бы изменить его с помощью StreamBuilder. что мне следует изменить в этом случае. Как правильно перейти на StreamBuilder?

это мой код:

Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;
    return SafeArea(     
        child: Center(
      child: Scaffold(     
          body: SingleChildScrollView(
              child: Form(
                  key: _formKey,
                  child: FutureBuilder(
                      future: future,
                      builder: (context, snapshot) {
                        switch (snapshot.connectionState) {
                          case ConnectionState.none:
                            return Text('no connection');
                          case ConnectionState.active:
                          case ConnectionState.waiting:
                            return Center(
                              child: CircularProgressIndicator(),
                            );
                            break;
                          case ConnectionState.done:
                            if (snapshot.hasError) {
                              return Text('error');
                            } else if (snapshot.hasData) {
                              return Column(
                                mainAxisAlignment:
                                    MainAxisAlignment.spaceEvenly,
                                children: [
                                  Container(
                                    padding: EdgeInsets.only(top: 16),
                                    width: MediaQuery.of(context).size.width,
                                    height:
                                        MediaQuery.of(context).size.height / 4,
                                    decoration: BoxDecoration(
                                        boxShadow: [
                                          BoxShadow(
                                              color: Colors.white60,
                                              blurRadius: 15.0,
                                              offset: Offset(0.0, 0.75))
                                        ],
                                        gradient: LinearGradient(
                                          begin: Alignment(0.5, 0.85),
                                          end: Alignment(0.48, -1.08),
                                          colors: [
                                            const Color(0xFF0B0C3A),
                                            const Color(0xFF010611),
                                          ],
                                          stops: [
                                            0.0,
                                            0.5,
                                          ],
                                        ),
                                        borderRadius: BorderRadius.only(
                                            bottomRight: Radius.circular(32),
                                            bottomLeft: Radius.circular(32))),
                                    child: Column(
                                      children: [
                                        Row(
                                          children: [
                                            SizedBox(
                                              width: 30,
                                            ),
                                            Column(
                                                crossAxisAlignment:
                                                    CrossAxisAlignment.start,
                                                children: [
                                                  Text(
                                                    "$name",
                                                    style: TextStyle(
                                                        color: Colors.white,
                                                        fontSize: 25,
                                                        fontWeight:
                                                            FontWeight.bold),
                                                  ),
                                                  SizedBox(
                                                    height: 10,
                                                  ),
                                                  Text(
                                                    "$phone",
                                                    style: TextStyle(
                                                      color: Colors.white60,
                                                      fontSize: 18,
                                        
                                        ),
                                        Row(
                                          mainAxisAlignment:
                                              MainAxisAlignment.end,
                                          children: [
                                            Container(
                                                margin: EdgeInsets.symmetric(
                                                    vertical: 10),
                                                width: size.width * 0.4,
                                                child: ElevatedButton(
                                                  onPressed: () {
                                                    if (_nameController.text ==
                                                            "" &&
                                                        _emailController.text ==
                                                            "" &&
                                                        _adressController
                                                                .text ==
                                                            "") {
                                                      setState(() =>
                                                          isButtonDisabled =
                                                              true);
                                                    } else {
                                                      editUserProfile();
                                                    }
                                                  },    
                                                  child: Text('Enregistrer'),
                                                  style:
                                                      ElevatedButton.styleFrom(
                                                    primary: Colors.transparent,
                                                    shape:
                                                        RoundedRectangleBorder(
                                                            borderRadius:
                                                                BorderRadius
                                                                    .circular(
                                                                        20),
                                                            side: BorderSide(
                                                                color: Colors
                                                                    .white)),
                                                  ),
                                                )),
                                            SizedBox(
                                              width: 20,
                                  Container(
                                    height: MediaQuery.of(context).size.height /
                                        1.5,
                                    child: Column(
                                      mainAxisAlignment:
                                          MainAxisAlignment.start,
                                      children: [
                                        Column(
                                          mainAxisAlignment:
                                              MainAxisAlignment.start,
                                          children: [
                                            Container(
                                              width: size.width * 0.94,
                                              child: Column(
                                                mainAxisAlignment:
                                                    MainAxisAlignment.start,
                                                children: [
                                                  Container(
                                                    padding: EdgeInsets.only(
                                                        left: 10,
                                                        right: 10,
                                                        bottom: 20,
                                                        top: 20),
                                                    child: Column(
                                                      mainAxisAlignment:
                                                          MainAxisAlignment
                                                              .start,
                                                      crossAxisAlignment:
                                                          CrossAxisAlignment
                                                              .start,
                                                      children: [
                                                        Row(
                                                          mainAxisAlignment:
                                                              MainAxisAlignment
                                                                  .spaceBetween,
                                                          children: [
                                                            Text(
                                                              'Votre nom :',
                                                              style: TextStyle(
                                                                  color: Color(
                                                                      0xFF4053FCF),
                                                                  fontSize: 16,
                                                                  fontWeight:
                                                                      FontWeight
                                                                          .w600),
                                                            ),
                                                            IconButton(
                                                                icon: Icon(
                                                                  CommunityMaterialIcons
                                                                      .pencil,
                                                                  color: Colors
                                                                      .grey,
                                                                ),

как я могу правильно перейти на StreamBuilder?
что мне следует изменить?

Мой экран:

введите описание изображения здесь


person lucky    schedule 29.05.2021    source источник


Ответы (1)


В основном это невозможно напрямую, потому что FutureBuilder принимает Future тип, тогда как StreamBuilder принимает Stream тип.

Future работает так же, как awaits для вещей (в основном вызовов удаленного API), которые должны быть выполнены, а затем, когда это сделано, он возвращает значение и это конец. Больше нет взаимодействия. Таким образом, он имеет единственное возвращаемое значение.

Однако Stream возвращает или yield значение постоянно, пока вы не остановите или dispose его. Таким образом, он может иметь бесконечное количество возвращаемых значений по времени.

В общем, если вы хотите использовать свой Future в StreamBuilder, это не сработает.

Я не знаю, что именно вы хотите, поэтому, если у вас есть дополнительные вопросы, дайте мне знать с комментариями, но если вы хотите превратить Future в Stream, вы можете использовать Stream.fromFuture(future). Однако это только yields одно событие и будет закрыто. Поэтому я думаю, что в этом нет никакого смысла, если у вас нет веских причин использовать StreamBuilder, хотя вам нужно только одно значение.

Но если вам нужно следить за изменениями данных, которые предоставляет Future, ответом может быть создание Stream с нуля.

Stream<Type> myStream() async* {
    while (true) 
    {
        final fetchedData = await yourFuture();
        yield fetchedData;
    }
}

Вышеупомянутая функция генерирует Stream, который продолжает вызывать ваш Future и yield присвоить значение Future, пока оно не будет удалено.

Теперь вы можете использовать StreamBuilder с Stream, которое вы сделали. Использование StreamBuilder очень похоже на использование FutureBuilder. Надеюсь, вы обратитесь к этой документации по классу StreamBuilder.

person CelesKang    schedule 29.05.2021
comment
Я обновил свой пост. Я хотел бы получать данные из SharedPrefences (локально), а не из api. но в то же время, возможно, мне следует изменить имя, например или адрес ... я думаю, что нужно перейти на streambuilder, чтобы решить эту проблему, но я думаю, что это неправильный путь - person lucky; 29.05.2021
comment
Как я могу получать данные локально и в то же время при желании изменять данные? @CelesKang - person lucky; 29.05.2021
comment
В основном "выборка" читается, а "изменять" - это правильно? Поэтому просто прочитайте данные из локальной базы данных, например SharedPreference, и обновите данные после. Я не знаю точно, что вы хотите, но вам не нужно обновлять данные в вашей локальной базе данных каждый раз, когда данные изменяются в результате взаимодействия с пользователем. Просто извлеките данные из своей локальной базы данных и сохраните их в состоянии, а когда все будет сделано на этой странице, обновите данные в своей локальной базе данных, прежде чем открывать или закрывать страницу. - person CelesKang; 30.05.2021
comment
Отлично, как данные обновляются на экране, не покидая страницы? - person lucky; 30.05.2021
comment
Теперь моя проблема в том, что данные будут обновлены, когда я в следующий раз войду в @CelesKang. - person lucky; 30.05.2021
comment
Вызовите метод обновления! Вам не нужно покидать страницу. В какой именно момент вы хотите обновить данные и в чем проблема, если данные будут изменены при следующем входе в систему? - person CelesKang; 30.05.2021
comment
владелец продукта хочет видеть новое значение, не покидая страницу профиля - person lucky; 30.05.2021
comment
Итак, проблема здесь в том, что вы сначала извлекаете данные из локальной базы данных, и они появляются, и когда вы редактируете их, нажимая кнопку со значком карандаша, вы обновляете значение в своей локальной базе данных, но они не отображаются на текущей странице Правильно? - person CelesKang; 30.05.2021
comment
Да, точно . для получения дополнительной информации: stackoverflow.com / questions / 67759132 / - person lucky; 30.05.2021
comment
Тогда не могли бы вы показать мне код для редактирования значения? editUserProfile() кажется единственным. Не могли бы вы показать мне его реализацию? - person CelesKang; 30.05.2021
comment
Позвольте нам продолжить это обсуждение в чате. - person lucky; 30.05.2021
comment
иди в чат @celeskang, пожалуйста - person lucky; 30.05.2021