Riverpod не меняет состояние

Я пытаюсь использовать Riverpod для управления сценой Flutter.

Я создал класс UsuarioProvider:

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shared_preferences/shared_preferences.dart';

class UsuarioProvider extends StateNotifier<String> {
  UsuarioProvider(): super("No user");

  void cambiarUsuario (String nuevo){

    state = nuevo;
    cambiarEmailUsuarioSP(nuevo);

  }
  cambiarEmailUsuarioSP(String nuevo) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    state =nuevo;
    prefs.setString("email", nuevo);
  }
  recibirEmailSP() async{
    SharedPreferences prefs = await SharedPreferences.getInstance();
    String emailActual = prefs.getString("email");

  }

}

На main.dart я объявил об использовании провайдера riverpod следующим образом:

//riverpod USUARIO
    final usuarioProvider = StateNotifierProvider<UsuarioProvider>((ref) {
      return UsuarioProvider();
    });
    void cambiarUsuario(String nueva) {
      context.read(usuarioProvider).cambiarUsuario(nueva);
    }

Теперь мне нужно изменить состояние UsuarioProvider следующим образом:

...
cambiarUsuario(parsed['user']['email'].toString());
...

Значение parsed['user']['email'].toString() = '[email protected]'

но затем, пытаясь получить для него состояние:

child: Consumer(builder: (_, ScopedReader watch, __) {
                var value = watch(usuarioProvider.state);
                print("%%%%%%%%%%%%%%%%%%EMail en Home:"+value.toString());
                if (value == "No user") {
                  value = 'NoClinic'.tr().toString();
                }
                return Text(
                  value.toString(),
                  style: TextStyle(
                    fontSize: 12.0,
                  ),
                );
              }),

Я всегда получаю "Нет пользователя", а не "[email protected]"

Что я делаю неправильно?


person mvasco    schedule 04.03.2021    source источник
comment
Где используется cambiarUsuario?, Попробуйте добавить оператор печати в cambiarUsuario, чтобы распечатать значение, которое вы используете для обновления состояния, просто чтобы убедиться, что провайдер его получил.   -  person 7mada    schedule 04.03.2021
comment
@MohammedAlfateh, я вставил заявление для печати: void cambiarUsuario (String nueva) {print (@@@@@@@@@@@@@@@@ ENTRO EN CAMBIAR USUARIO: + nueva); context.read (usuarioProvider) .cambiarUsuario (новая); } и вывод показывает строку, как и должно: / I / flutter (14342): @@@@@@@@@@@@@@@ ENTRO EN CAMBIAR USUARIO: [email protected], но состояние не изменено   -  person mvasco    schedule 04.03.2021
comment
Я хочу напечатать состояние, хорошо, я прав, как ответ, только потому, что код не читается в разделе комментариев.   -  person 7mada    schedule 04.03.2021


Ответы (1)


файл провайдера:

import 'package:riverpod/riverpod.dart';

final usuarioProvider = StateNotifierProvider<UsuarioProvider>((ref) {
  return UsuarioProvider();
});

class UsuarioProvider extends StateNotifier<String> {
  UsuarioProvider() : super("No user");

  void cambiarUsuario(String nuevo) {
    state = nuevo;
    cambiarEmailUsuarioSP(nuevo);
  }

  cambiarEmailUsuarioSP(String nuevo) async {
    await Future.delayed(Duration(seconds: 1));
    
    // this isn't necessary and it will case aditional rebuilt
    state = nuevo;
  }
}

Экран :

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Consumer(
              builder: (context, watch, child) {
                var value = watch(usuarioProvider.state);
                if (value == "No user") {
                  value = 'NoClinic';
                }
                return Text(value);
              },
            ),
            SizedBox(height: 50),
            ElevatedButton(
              onPressed: () {
                context.read(usuarioProvider).cambiarUsuario("It work !");
              },
              child: Text("test"),
            )
          ],
        ),
      ),
    );
  }
}

убедитесь, что для добавления области поставщика:

void main() => runApp(ProviderScope(child: MyApp()));
person 7mada    schedule 04.03.2021
comment
позвольте мне попробовать ваше предложение - person mvasco; 04.03.2021
comment
он работает, это результат: +4 мс] I / flutter (19288): nuevo is [email protected] [] I / flutter (19288): state is [email protected] - person mvasco; 04.03.2021
comment
тогда почему состояние в виджете Consumer не меняется? - person mvasco; 04.03.2021
comment
Возможно, с тех пор это не сработает, но это всего лишь попытка. Попробуйте использовать конструктор по умолчанию для потребителя или (сниппет) вместо того, чтобы давать ему оценку ниже и область видимости только (context, watch, - person 7mada; 04.03.2021
comment
Не могли бы вы проверить, объявлен ли виджет Consumer должным образом? - person mvasco; 04.03.2021
comment
он находится в другом классе, а не в main.dart - person mvasco; 04.03.2021
comment
Я отредактирую ваш ответ, чтобы показать вам весь мой код, связанный с поставщиком в другом классе. - person mvasco; 04.03.2021
comment
Хорошо, я также хотел бы знать, объявлен ли предоставленный usuarioProvider как глобальная переменная (не внутри какого-либо класса) или нет. - person 7mada; 04.03.2021
comment
да, он объявлен внутренним классом HomeScreen, как вы можете видеть в моем последнем редактировании вашего ответа - person mvasco; 04.03.2021
comment
Объявление провайдера должно находиться вне любого класса как глобальная переменная. - person 7mada; 04.03.2021
comment
позволь мне попробовать, пожалуйста - person mvasco; 04.03.2021
comment
Безуспешно, остается прежним, виджет-потребитель не получает статус "Пользователь", а не'[email protected] - person mvasco; 04.03.2021
comment
Да чуть ниже импорта. - person mvasco; 04.03.2021
comment
Да, я только что увидел ответ, я попробую запустить тот же код на своей машине и дать обновление, дайте мне 5 минут - person 7mada; 04.03.2021
comment
Да, конечно, я буду ждать тебя. - person mvasco; 04.03.2021
comment
Если я изменяю состояние непосредственно в классе провайдера, он работает, состояние меняется в HomeScreen. Это все немного странно. - person mvasco; 04.03.2021
comment
Я попробовал, и это сработало, но я не использовал SharedPreferences, а вместо этого добавил задержку, я загружу весь код. - person 7mada; 04.03.2021
comment
Приятно я буду ждать тебя - person mvasco; 04.03.2021
comment
Давайте продолжим это обсуждение в чате. - person 7mada; 04.03.2021