简体   繁体   English

Flutter 创建实体后的 Riverpod 重定向

[英]Flutter Riverpod redirection after entity creation

I'm working on my Flutter app and I try to set up a redirection process after creating an entity (user).我正在开发我的 Flutter 应用程序,我尝试在创建实体(用户)后设置重定向过程。 The state management is handled by Riverpod. state 管理由 Riverpod 处理。 I'm using Firebase for the auth and Postgres for the database.我将 Firebase 用于身份验证,将 Postgres 用于数据库。

The insert method in the repository returns a User.存储库中的 insert 方法返回一个用户。 With a StateNotifier I just want to check if the method returns a user.使用StateNotifier我只想检查该方法是否返回用户。 If the user is returned I set a success state object (CreateAccountStateSuccess), if it's not I set an error state object with a message. If the user is returned I set a success state object (CreateAccountStateSuccess), if it's not I set an error state object with a message. Problem: my saveUser method always return null in my StateNotifier , even though my user is persisted in Firebase and my database.问题:我的saveUser方法总是在我的StateNotifier中返回null ,即使我的用户保存在 Firebase 和我的数据库中。 I think it's a Riverpod issue.我认为这是一个 Riverpod 问题。 Any idea?任何想法?

My repository:我的存储库:

  Future<AppUser?> saveUser(String email, String nickname, String role,
      String firstname, String lastname) async {
    try {
      connection.open().then((value) async {
        Future<List<Map<String, Map<String, dynamic>>>> result = connection.mappedResultsQuery(
          'insert into public.user(email,nickname,role,firstname,lastname) '
          'values(@emailValue,@nicknameValue,@roleValue,@firstnameValue,@lastnameValue) '
          'returning *',
          substitutionValues: {
            'emailValue': email,
            'nicknameValue': nickname,
            'roleValue': role,
            'firstnameValue': firstname,
            'lastnameValue': lastname,
          },
          allowReuse: true,
          timeoutInSeconds: 30,
        );
        result.then((value) {
          final userFromDataBase = value[0]['user']!;
          return AppUser(
              email: userFromDataBase['email'],
              nickname: userFromDataBase['nickname'],
              role: userFromDataBase['role'],
              firstname: userFromDataBase['firstname'],
              lastname: userFromDataBase['lastname']
          );
        });
      });
    } catch (e) {
      print(ErrorHandler(message: e.toString()));
      return null;
    }
    return null;
  }

My Firebase method to create user for Firebase and using my repository method:我的 Firebase 方法为 Firebase 创建用户并使用我的存储库方法:

  Future<AppUser?> registerWithEmailAndPassword(String email, String password, String nickname, String role, String firstname, String lastname) async {
    FirebaseApp app = await Firebase.initializeApp(
        name: 'Secondary', options: Firebase.app().options);
    try {
      UserCredential result =
      await FirebaseAuth.instanceFor(app: app).createUserWithEmailAndPassword(email: email, password: password);
      User? user = result.user;
      if (user == null) {
        throw Exception("No user found");
      } else {
        try {
          return await UserRepository(user.email!).saveUser(email, nickname, role, firstname, lastname);
        } on PostgreSQLException catch (e) {
          print('CATCH POSTGRES EXCEPTION');
          print(ErrorHandler(message: e.code.toString()));
        }
      }
    } on FirebaseException catch (e) {
      print('CATCH FIREBASE EXCEPTION');
      print(ErrorHandler(message: e.code.toString()));
    }
    return null;
  }

My controller:我的 controller:

class CreateAccountController extends StateNotifier<CreateAccountState> {
  CreateAccountController(this.ref) : super(const CreateAccountStateInitial());

  final Ref ref;

  void register(String email, String password, String nickname, String role, String firstname, String lastname) async {
    state = const CreateAccountStateLoading();
    try {
      await ref.read(authRepositoryProvider).registerWithEmailAndPassword(
        email,
        password,
        nickname,
        role,
        firstname,
        lastname
      ).then((user){
        user != null ? state = const CreateAccountStateSuccess() : state = const CreateAccountStateError('Something went wrong with the user creation in database');
      });
    } catch (e) {
      state = CreateAccountStateError(e.toString());
    }
  }
}

final createAccountControllerProvider =
StateNotifierProvider<CreateAccountController, CreateAccountState>((ref) {
  return CreateAccountController(ref);
});

My state objects:我的 state 对象:

class CreateAccountState extends Equatable {
  const CreateAccountState();

  @override
  List<Object> get props => [];
}

class CreateAccountStateInitial extends CreateAccountState {
  const CreateAccountStateInitial();

  @override
  List<Object> get props => [];
}

class CreateAccountStateLoading extends CreateAccountState {
  const CreateAccountStateLoading();

  @override
  List<Object> get props => [];
}

class CreateAccountStateSuccess extends CreateAccountState {
  const CreateAccountStateSuccess();

  @override
  List<Object> get props => [];
}

class CreateAccountStateError extends CreateAccountState {
  final String error;

  const CreateAccountStateError(this.error);

  @override
  List<Object> get props => [error];
}

My screen:我的屏幕:

class CreateAccountScreen extends StatefulHookConsumerWidget {
  const CreateAccountScreen({Key? key}) : super(key: key);

  @override
  ConsumerState<CreateAccountScreen> createState() => _CreateAccountScreenState();
}

class _CreateAccountScreenState extends ConsumerState<CreateAccountScreen> {
  TextEditingController emailController = TextEditingController();
  TextEditingController passwordController = TextEditingController();
  TextEditingController nicknameController = TextEditingController();
  TextEditingController roleController = TextEditingController();
  TextEditingController firstnameController = TextEditingController();
  TextEditingController lastnameController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    ref.listen<CreateAccountState>(createAccountControllerProvider, ((previous, state) {
      if (state is CreateAccountStateError) {
        ScaffoldMessenger.of(context).showSnackBar(SnackBar(
          content: Text(state.error.toString()),
          backgroundColor: Colors.red,
        ));
      }
      print(state.toString());
      if (state is CreateAccountStateSuccess) {
        context.goNamed('/', params:
        {
          'screenName': 'users'
        });
      }
    }));

    return Scaffold(
      appBar: AppBar(
          title: const Text('Create an account'),
          elevation: 8.0,
          backgroundColor: Colors.deepOrangeAccent,
          actions: [
            TextButton.icon(
              icon: const Icon(
                Icons.logout_rounded,
                color: Colors.white,
              ),
              label: const Text('', style: TextStyle(color: Colors.white)),
              onPressed: () async {
                ref.read(loginControllerProvider.notifier).signOut();
              },
            ),
          ]
      ),
      body: Padding(
          padding: const EdgeInsets.all(10),
          child: ListView(
            children: <Widget>[
              Container(
                  alignment: Alignment.center,
                  padding: const EdgeInsets.all(10),
                  child: const Text(
                    'Ludocal 2',
                    style: TextStyle(
                        color: Colors.deepOrange,
                        fontWeight: FontWeight.w500,
                        fontSize: 30),
                  )),
              Container(
                padding: const EdgeInsets.all(10),
                child: TextFormField(
                  validator: (value) =>
                  value == null || value.isEmpty ? "Enter an email" : null,
                  controller: emailController,
                  decoration: const InputDecoration(
                    border: OutlineInputBorder(),
                    labelText: 'Email Address',
                  ),
                ),
              ),
              Container(
                padding: const EdgeInsets.fromLTRB(10, 10, 10, 0),
                child: TextFormField(
                  obscureText: true,
                  validator: (value) =>
                  value == null || value.isEmpty ? "Enter a password" : null,
                  controller: passwordController,
                  decoration: const InputDecoration(
                    border: OutlineInputBorder(),
                    labelText: 'Password',
                  ),
                ),
              ),
              Container(
                padding: const EdgeInsets.fromLTRB(10, 10, 10, 0),
                child: TextFormField(
                  validator: (value) =>
                  value == null || value.isEmpty ? "Enter a nickname" : null,
                  controller: nicknameController,
                  decoration: const InputDecoration(
                    border: OutlineInputBorder(),
                    labelText: 'Nickname',
                  ),
                ),
              ),
              Container(
                padding: const EdgeInsets.fromLTRB(10, 10, 10, 0),
                child: TextFormField(
                  validator: (value) =>
                  value == null || value.isEmpty ? "Enter a role" : null,
                  controller: roleController,
                  decoration: const InputDecoration(
                    border: OutlineInputBorder(),
                    labelText: 'Role',
                  ),
                ),
              ),
              Container(
                padding: const EdgeInsets.fromLTRB(10, 10, 10, 0),
                child: TextFormField(
                  validator: (value) =>
                  value == null || value.isEmpty ? "Enter a firstname" : null,
                  controller: firstnameController,
                  decoration: const InputDecoration(
                    border: OutlineInputBorder(),
                    labelText: 'Firstname',
                  ),
                ),
              ),
              Container(
                padding: const EdgeInsets.fromLTRB(10, 10, 10, 0),
                child: TextFormField(
                  validator: (value) =>
                  value == null || value.isEmpty ? "Enter a lastname" : null,
                  controller: lastnameController,
                  decoration: const InputDecoration(
                    border: OutlineInputBorder(),
                    labelText: 'Lastname',
                  ),
                ),
              ),
              Container(
                  height: 50,
                  padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
                  margin: const EdgeInsets.only(top:20),
                  child: ElevatedButton(
                    child: const Text('Create', style: TextStyle(color: Colors.white)),
                    onPressed: () {
                      ref
                          .read(createAccountControllerProvider.notifier)
                          .register(emailController.text, passwordController.text, nicknameController.text,
                      roleController.text, firstnameController.text, lastnameController.text);
                    },
                  )),
            ],
          )),
    );
  }
}

The problem is in the saveUser function.问题出在saveUser function 中。 Instead of using .then use await .而不是使用.then使用await It would be like the following:如下所示:

Future<AppUser?> saveUser(String email, String nickname, String role,
    String firstname, String lastname) async {
  try {
    await connection.open();
    final result = await connection.mappedResultsQuery(
      'insert into public.user(email,nickname,role,firstname,lastname) '
      'values(@emailValue,@nicknameValue,@roleValue,@firstnameValue,@lastnameValue) '
      'returning *',
      substitutionValues: {
        'emailValue': email,
        'nicknameValue': nickname,
        'roleValue': role,
        'firstnameValue': firstname,
        'lastnameValue': lastname,
      },
      allowReuse: true,
      timeoutInSeconds: 30,
    );

    final userFromDataBase = result[0]['user']!;
    return AppUser(
      email: userFromDataBase['email'],
      nickname: userFromDataBase['nickname'],
      role: userFromDataBase['role'],
      firstname: userFromDataBase['firstname'],
      lastname: userFromDataBase['lastname'],
    );
  } catch (e) {
    print(ErrorHandler(message: e.toString()));
    return null;
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM